web-dev-qa-db-fra.com

Appel de la méthode de classe d'activité depuis la classe de service

J'ai vu beaucoup de publications dans SO à ce sujet, mais je ne pouvais pas obtenir le moyen exact et le plus facile d'appeler une méthode d'activité à partir de la classe de service. Le récepteur de radiodiffusion est-il la seule option? Pas de sortie facile? Il me suffit d'appeler la méthode suivante dans la classe d'activité une fois le lecteur multimédia préparé en classe de service.

Classe d'activité:

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

Classe de service:

   @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 
  }
41
Siju

Définissez une interface que votre service utilisera pour communiquer des événements:

public interface ServiceCallbacks {
    void doSomething();
} 

Ecrivez votre classe de service. Votre activité sera liée à ce service, alors suivez l'exemple illustré ci-dessous . De plus, nous allons ajouter une méthode pour définir la variable 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;
    }
}

Écrivez votre classe d'activité en suivant le même guide, mais faites-la également implémenter votre interface ServiceCallbacks. Lorsque vous liez/dissociez du service, vous l'enregistrez/le désinscrivez en appelant setCallbacks sur le service.

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() {
        ...
    }
}

Désormais, lorsque votre service souhaite communiquer avec l'activité, appelez simplement l'une des méthodes d'interface précédemment. Dans votre service:

if (serviceCallbacks != null) { 
    serviceCallbacks.doSomething();
}
83
Karakuri

Utilisez Broadcast receiver with service pour mettre à jour votre vue à partir de la classe de service . Par exemple:

  1. Dans mon cours d'activité

    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));
        }
    }
    

    Et dans ma classe de service, j'appelle mon interface de mise à jour après un intervalle de temps qui met à jour mon interface utilisateur.

    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);
            }
     }
    

Pour le code complet, vérifiez ceci link

5
Mukesh Y

J'ai créé une classe générale appelée Delegate (ce n'est pas un nom spécial, vous pouvez l'appeler John) et lui ai passé la classe MainActivity sous forme de champ statique. Ensuite, je peux y accéder à partir du service depuis son global maintenant. Je ne suis pas sûr que ce soit rentable, mais cela a résolu le problème pour moi simplement.

Mon service: 

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 déléguée:

package com.some.package;

public class Delegate {
    static MainActivity theMainActivity;
}

Ce que j'ai fait dans 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);
}
2
fenadoruk

Vous ne pouvez pas appeler votre méthode de services directement de votre activité ou inversement. Il y a 3 façons de communiquer avec un service. en utilisant des diffuseurs et des récepteurs, en utilisant Messenger ou en liant le service. Pour plus d'informations, consultez http://developer.Android.com/guide/components/bound-services.html

0
Onur