How to receive automatically, in Activity, a value calculated in a Service?

Asked

Viewed 161 times

3

I have an algorithm that generates prime numbers using a Service. Well, it works but I need it to update the data in my Activity automatically, at the moment it does this just by clicking on a button and need it to be done automatically.

I mean, send it to mine textView always the last prime number generated on service automatically. Any ideas? I’m a beginner and would appreciate it if you could be very specific with examples I can use.

public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {

    private Chronometer cro;
    private TextView tvCampo;
    private Contador.ContadorServiceBinder binder = null;

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

        cro = (Chronometer) findViewById(R.id.cro);
        tvCampo = (TextView) findViewById(R.id.campoTexto);
        findViewById(R.id.botao).setOnClickListener(this);

        startService(Contador.i(this));
        bindService(Contador.i(this), this, BIND_AUTO_CREATE);

    }

    @Override
    public void onClick(View v) {
        cro.start();
        tvCampo.setText(String.valueOf(binder.getPrimo()));
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (binder == null) {
            unbindService(this);
            binder = null;
        }
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (Contador.ContadorServiceBinder) service;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        binder = null;
    }
}

Here’s my Activity who inherits from Service:

public class Contador extends Service {

    public int primo = 0;
    private Boolean ativo = false;
    private ContadorServiceBinder binder = new ContadorServiceBinder();

    public static Intent i(Context context) {
        return new Intent(context, Contador.class);
    }

    @Override
    public void onCreate() {

        if (!ativo) {
            ativo = true;

            new Thread() {

                public void run() {

                    int i = 2;
                    int j = 1;
                    int contador = 0;

                    while (i <= 1000000000) {
                        while (j <= i) {
                            if (i % j == 0) {
                                contador++;
                            }
                            j = j + 1;
                        }

                        if (contador == 2) {
                            primo = i;
                        }

                        i = i + 1;
                        j = 1;
                        contador = 0;
                    }
                }
            }.start();

        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        ativo = false;
        primo = 0;
        binder = null;
    }

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

    public class ContadorServiceBinder extends Binder {

        public int getPrimo() {
            return primo;
        }
    }
}
  • The simplest way is to pass the textview in the service constructor. and update it through there, is not the best way, but is the simplest.

1 answer

1


One of the possible ways for the Service communicate with the Activity is to use Localbroadcastmanager to generate a broadcast to be received by Activity

Service

Start by declaring constants to be used to launch the broadcast:

//A *Action* para criar o *Intent*
public static final String ACTION_PRIME_CALCULATED = "oSeuPackageName.PRIME_CALCULATED";

//Chave para aceder ao *Extra* que guarda o valor do *primo*
public static final String PRIME_VALUE = "prime value";

Then state the method for launching the broadcast:

private void sendBroadcast(int primo){
    Intent intent = new Intent(ACTION_PRIME_CALCULATED)
                        .addCategory(Intent.CATEGORY_DEFAULT)
                        .putExtra(PRIME_VALUE, primo);
    LocalBroadcastManager.getInstance(this)
                         .sendBroadcast(intent);
}

At the end of the prime number calculation call this method:

@Override
public void onCreate() {

    if (!ativo) {
        ativo = true;

        new Thread() {

            public void run() {

                int i = 2;
                int j = 1;
                int contador = 0;

                while (i <= 1000000000) {

                    ....
                    ....
                }
                sendBroadcast(int primo);
            }
        }.start();

    }
}

Activity

Declare a Broadcastreceiver to receive the value of the calculated prime number:

private class PrimeValueReceiver extends BroadcastReceiver {

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

        int primo = intent.getIntExtra(Contador.PRIME_VALUE,0);
        //Actualiza o TextView
        updateTextView(primo);
    }
}

In the method onCreate create an instance of Primevaluereceiver:

private PrimeValueReceiver primeValueReceiver;

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

    ....
    ....
}

In the method onResume register the Broadcastreceiver:

@Override
protected void onResume() {
    super.onResume();

    IntentFilter intentFilter = new IntentFilter(Contador.ACTION_PRIME_CALCULATED);
    intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
    LocalBroadcastManager.getInstance(this)
                         .registerReceiver(primeValueReceiver, intentFilter);
}

In the method onPause do the unregister of Broadcastreceiver:

@Override
protected void onPause() {
    super.onPause();

    //Unregister BroadcastReceiver.
    LocalBroadcastManager.getInstance(this)
      .unregisterReceiver(primeValueReceiver);
}

Only the method for updating the Textview:

private void updateTextView(int primo){

    tvCampo.setText(String.valueOf(primo));
}

Another possible approach is to use Messager and Handler to make the communication Activity <-> Service. See here a example.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.