Vincenzo Cocciolo
Vincenzo Cocciolo

Reputation: 31

Android: Access a MainActivity function from other class class

I found many similar answered issues here at SO but all of them seems to me slighty different from the mine.

I have my MainActivity Class that recall the addInfo() function defined in the same class. Consider also that addInfo function access the activity_ main Layout.:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ...
        String[] saInfoTxt = {"App Started"};
        addInfo("APP",saInfoTxt);
        ...

    }


    public void addInfo(String sType, String[] saInfoTxt) {

        Date dNow = Calendar.getInstance().getTime();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
        String sNow = dateFormat.format(dNow);

        LinearLayout layout = (LinearLayout) findViewById(R.id.info);
        String sInfoTxt =TextUtils.join("\n", saInfoTxt);
        sInfoTxt= sType + " " + sNow + "\n" + sInfoTxt;

        TextView txtInfo = new TextView(this);
        txtInfo.setText(sInfoTxt);
        txtInfo.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));
        ((LinearLayout) layout).addView(txtInfo);
    };   
}

Now I have a second class that respond to a Receiver to intercept incoming SMS. This class needs to recall the MainActivity.addInfo() function but I'm not able to do so:

public class SmsReceiver extends BroadcastReceiver {

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

        if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                // get sms objects
                Object[] pdus = (Object[]) bundle.get("pdus");
                if (pdus.length == 0) {
                    return;
                }
                // large message might be broken into many
                SmsMessage[] messages = new SmsMessage[pdus.length];
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < pdus.length; i++) {
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                    sb.append(messages[i].getMessageBody());
                }
                String sender = messages[0].getOriginatingAddress();
                String message = sb.toString();

                String[] saInfoTxt = {"Sender: " + sender,"Message: " + message};
                MainActivity.addInfo("SMS", saInfoTxt);

            }
        }
    }
}

If I define the addInfo() as static then the internal code is faulty. If I leave it as non-static the second class doesn't see the addInfo()

Could someone point me to the right direction?

Thanks in advance

Upvotes: 0

Views: 1181

Answers (4)

kuber singh
kuber singh

Reputation: 279

Create Interface:

public Interface CallBackInterface{
void getData(String key, String[] arr);
}

On Application Class :

public class BaseApplication extends Application
{
CallBackInterface event=null;
....// getter and setter 
 void setEvent(CallBackInterface event)
 {
  this.event=event;
 }
}

on Activity Class:

BaseApplication.getInstance.setEvent(new CallBackInterface()
{
        @Override
        public void getData(String key,String[] arr) {
          //stuff to do....
        }
});

on SmsReceiver class

....
if(BaseApplication.getInstance.getEvent!=null){
BaseApplication.getInstance.getEvent.sendData("SMS", saInfoTxt);
}

Upvotes: 0

Robert K.
Robert K.

Reputation: 1073

One of the simplest solutions in your case would be to use EventBus or similar to broadcast events across application components. Since your Activity might not be alive when BroadcastReceiver is receiving an intent, you need loose coupling between your Activity and Receiver.

Here is an example implementation using EventBus, make sure to include it in your dependencies first (https://github.com/greenrobot/EventBus):

// Event.java

class Event {
    private String text;
    private String[] array;

    public Event(String text, String[] array) {
        this.text = text;
        this.array = array;
    }

    public String getText() { return text; }

    public String[] getArray() { return array; }
}

// SmsReceiver.java (instead of calling activity directly)

EventBus.getDefault().post(new Event("SMS", saInfoTxt));

// MainActivity.java

void onCreate() {
    ..
    EventBus.getDefault().register(this); // registers event listener
}

void onDestroy() {
    EventBus.getDefault().unregister(this); // unregister event listener (important!)
}

@Subscribe(threadMode = ThreadMode.MAIN) 
void onEvent(Event event) {
    addInfo(event.getText(), event.getArray());
}

If you want to solve it without EventBus or RxJava, you could also send an Intent to your Activity and handle data in Activity.onNewIntent().

Upvotes: 0

Innomotion Media
Innomotion Media

Reputation: 53

Either move all code that is needed from other classes into one class and make this class static. if this is not an option make your activity be a single instance:

    public static MainActivity Instance;

OnCreate:

        Instance = this;

Now call whereever you are:

MainActivity.Instance.addInfo();

Upvotes: 0

Abdul Waheed
Abdul Waheed

Reputation: 4678

If this is the case, you need to extract your method and made a new class where you write you all business related code. When keep your business related code isolated in other class, then you are easily able to call or access your business method in every activity very easily. Or you can make sort of utility class.

Upvotes: 1

Related Questions