2014-05-10 16 views
32

Ho visto molti post in SO per quanto riguarda questo, ma non ho potuto ottenere il modo esatto e più semplice per chiamare un metodo di attività dalla classe di servizio. Il ricevitore broadcast è solo l'opzione? Non è facile uscirne ? Devo solo richiamare il seguente metodo nella classe Activity dopo che il lettore multimediale è stato preparato nella classe Service.Chiamare il metodo della classe di attività dalla classe di servizio

Classe di attività: classe

public void updateProgress() { 
    // set Progress bar values 
    songProgressBar.setProgress(0); 
    songProgressBar.setMax(100); 
    // Updating progress bar 
    updateProgressBar(); 
} 

Servizio:

@Override 
public IBinder onBind(Intent intent) { 
    Log.d(this.getClass().getName(), "BIND"); 
    return musicBind; 
} 

@Override 
public boolean onUnbind(Intent intent) { 
    return false; 
} 
    @Override 
public void onPrepared(MediaPlayer mp) { 
    try { 
     mp.start(); 
    } catch (IllegalStateException e) { 
     e.printStackTrace(); 
    } 

      // updateProgress();// Need to call the Activity method here 
    } 

risposta

66

definire un'interfaccia vostro servizio utilizzerà per comunicare eventi:

public interface ServiceCallbacks { 
    void doSomething(); 
} 

Scrivi la classe di servizio. La tua attività si collegherà a questo servizio, quindi segui lo sample shown here. Inoltre, aggiungeremo un metodo per impostare lo ServiceCallbacks.

public class MyService extends Service { 
    // Binder given to clients 
    private final IBinder binder = new LocalBinder(); 
    // Registered callbacks 
    private ServiceCallbacks serviceCallbacks; 


    // Class used for the client Binder. 
    public class LocalBinder extends Binder { 
     MyService getService() { 
      // Return this instance of MyService so clients can call public methods 
      return MyService.this; 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return binder; 
    } 

    public void setCallbacks(ServiceCallbacks callbacks) { 
     serviceCallbacks = callbacks; 
    } 
} 

Scrivere la classe di attività seguendo la stessa guida, ma anche implementare l'interfaccia ServiceCallbacks. Quando esegui il binding/unbind dal servizio, lo registrerai/annullerai la registrazione chiamando il servizio setCallbacks.

public class MyActivity extends Activity implements ServiceCallbacks { 
    private MyService myService; 
    private boolean bound = false; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(...); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     // bind to Service 
     Intent intent = new Intent(this, MyService.class); 
     bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     // Unbind from service 
     if (bound) { 
      myService.setCallbacks(null); // unregister 
      unbindService(serviceConnection); 
      bound = false; 
     } 
    } 

    /** Callbacks for service binding, passed to bindService() */ 
    private ServiceConnection serviceConnection = new ServiceConnection() { 

     @Override 
     public void onServiceConnected(ComponentName className, IBinder service) { 
      // cast the IBinder and get MyService instance 
      LocalBinder binder = (LocalBinder) service; 
      myService = binder.getService(); 
      bound = true; 
      myService.setCallbacks(MyActivity.this); // register 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName arg0) { 
      bound = false; 
     } 
    }; 

    /* Defined by ServiceCallbacks interface */ 
    @Override 
    public void doSomething() { 
     ... 
    } 
} 

Ora quando il servizio desidera comunicare di nuovo all'attività, è sufficiente chiamare uno dei metodi di interfaccia precedenti. All'interno vostro servizio:

if (serviceCallbacks != null) { 
    serviceCallbacks.doSomething(); 
} 
+0

Questo ha risolto il mio problema. Grazie mille :) – Siju

+0

Grazie! Ci sono alcuni dettagli non abbastanza chiari negli sviluppatori Android. Questo mi ha aiutato! –

+0

Grazie. Fornisce un esempio perfetto –

-1

È possibile chiamare dal proprio servizio

getContentResolver().notifyChange(uri, null); 

e nella vostra attività si imposta un

getContentResolver().registerContentObserver(uri, false, new ContentObserver(getHandler()) 
{ 
    public void onChange(boolean selfChange) 
    { 
     updateProgress() 
    } 
}; 

il metodo onChange

sarà ba invitato il thread UI

+0

quello che dovrebbe essere il valore di uri? Non penso che il tuo codice verrà compilato. – likejiujitsu

3

Utilizzare il ricevitore Broadcast con servizio per l'aggiornamento della vista dalla classe di servizio. Per esempio:

  1. Nella mia classe di attività

    public class ServiceDemoActivity extends Activity { 
    
        Intent intent; 
        /** Called when the activity is first created. */ 
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.main); 
         final TextView notification = (TextView) findViewById(R.id.notification); 
         if (CheckIfServiceIsRunning()) { 
    
         } else { 
          startService(new Intent(this, MyService.class)); 
         } 
        } 
    
        private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
         @Override 
         public void onReceive(Context context, Intent intent) { 
          updateDate(intent); 
         } 
        }; 
    
        private void updateDate(Intent intent) { 
         String time = intent.getStringExtra("time"); 
         Toast.makeText(getApplicationContext(), "Yea!!! Service called", Toast.LENGTH_SHORT).show(); 
         TextView date = (TextView) findViewById(R.id.date); 
         date.setText(time); 
        } 
    
        @Override 
        public void onResume() { 
         super.onResume(); 
         registerReceiver(broadcastReceiver, new IntentFilter(
           MyService.BROADCAST_ACTION)); 
        } 
    } 
    

    E nella mia classe di servizio che io chiamo il mio aggiornamento ui dopo qualche intervallo di tempo che aggiorna il mio UI.

    public class MyService extends Service {  
    
         public static final String 
         BROADCAST_ACTION = "com.mukesh.service";  
         private final Handler handler = new Handler(); 
    
    
         @Override 
         public void onCreate() { 
    
          intent = new Intent(BROADCAST_ACTION); 
         } 
    
         @Override 
         public void onDestroy() { 
    
          stopService(intent); 
         } 
    
         @Override 
         public void onStart(Intent intent, int startid) { 
          int i = 0; 
          while (i <= 2) { 
           if (i > 1) { 
            i++; 
            this.onDestroy(); 
           } else { 
            counter = i; 
            i++; 
            handler.removeCallbacks(sendUpdatesToUI); 
            handler.postDelayed(sendUpdatesToUI, 1 * 1000); // 1 sec 
           } 
          }  
         } 
    
         private Runnable sendUpdatesToUI = new Runnable() { 
          public void run() { 
           DisplayLoggingInfo();   
             handler.postDelayed(this, 7 * 1000); // 7 sec 
          } 
         }; 
    
         private void DisplayLoggingInfo() { 
          intent.putExtra("time", new Date().toLocaleString()); 
          intent.putExtra("counter", String.valueOf(counter)); 
          sendBroadcast(intent); 
          stopService(intent); 
         } 
    } 
    

Per il check codice completo questo link

2

ho creato una classe generale chiamato Delegate (non è un nome speciale, è possibile il nome che John) e superato classe MainActivity in esso come un campo statico. Quindi posso accedervi dal servizio poiché è globale ora.Non sono sicuro che sia economico ma ha risolto il problema per me semplice.

Il mio servizio:

package com.some.package; 
import com.google.firebase.iid.FirebaseInstanceId; 
import com.google.firebase.iid.FirebaseInstanceIdService; 

public class FirebaseInstanceIDService extends FirebaseInstanceIdService { 

    @Override 
    public void onTokenRefresh() { 
     String token = FirebaseInstanceId.getInstance().getToken(); 
     Delegate.theMainActivity.onDeviceTokenChange(token); 
    } 
} 

classe Delegate:

package com.some.package; 

public class Delegate { 
    static MainActivity theMainActivity; 
} 

Quello che ho fatto in MainActivity:

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    Delegate.theMainActivity = this; 

    //rest of the code... 
} 

public void onDeviceTokenChange(String token){ 
    Log.e("updated token:", token); 
} 
+1

questa è una perdita di memoria –

Problemi correlati