Подтвердить что ты не робот

Вызов метода класса активности из класса обслуживания

Я видел много сообщений в SO относительно этого, но не смог получить точный и самый простой способ вызова метода активности из класса сервиса. Есть ли приемник только для передачи? Нет простого выхода? Мне просто нужно вызвать следующий метод в классе Activity после того, как медиапроигрыватель подготовлен в классе Service.

Класс действия:

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

Класс обслуживания:

   @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 
  }
4b9b3361

Ответ 1

Определите интерфейс, который ваша Служба будет использовать для обмена событиями:

public interface ServiceCallbacks {
    void doSomething();
} 

Напишите свой класс обслуживания. Ваша активность будет привязана к этой службе, поэтому следуйте приведенному здесь примеру . Кроме того, мы добавим метод установки 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;
    }
}

Напишите свой класс активности по тому же руководству, но также заставьте его реализовать интерфейс ServiceCallbacks. Когда вы привязываетесь/отвязываетесь от Сервиса, вы регистрируете/отменяете его, вызывая 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() {
        ...
    }
}

Теперь, когда ваш сервис хочет вернуться к активности, просто вызовите один из методов интерфейса из более раннего. Внутри вашей службы:

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

Ответ 2

Использовать широковещательный приемник с услугой для обновления вашего представления из класса обслуживания. Например:

  • В классе активности

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

    И в моем классе обслуживания я вызываю свое обновление 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);
            }
     }
    

Для полного кода проверьте эту ссылку

Ответ 3

Я создал общий класс под названием Delegate (это не специальное имя, вы можете назвать его John) и передал ему класс MainActivity как статическое поле. Тогда я могу получить доступ к нему со службы с момента его создания. Я не уверен, что он экономичен, но он решил проблему для меня просто.

Мой сервис:

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

Класс делегата:

package com.some.package;

public class Delegate {
    static MainActivity theMainActivity;
}

Что я сделал в 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);
}

Ответ 4

Вы не можете напрямую вызвать свой метод sevices из своей активности или наоборот. Существует 3 способа связи с услугой; используя вещатели и приемники, используя Messenger или привязки к службе. Для получения дополнительной информации смотрите http://developer.android.com/guide/components/bound-services.html

Ответ 5

Вы можете позвонить со своего сервиса

 getContentResolver().notifyChange(uri, null);

и в вашей деятельности вы настроили

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

метод onChange будет вызван на поток пользовательского интерфейса