call activity method from broadcast receiver - android

In the main activity, a layout is loaded that has some input fields and a submit button. When the submit button is clicked, the onClick handler method sends an sms back to the same mobile number :
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(number, null, "hi", null, null);
There is a broadcast receiver defined that intercepts the message :
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle pdusBundle = intent.getExtras();
Object[] pdus=(Object[])pdusBundle.get("pdus");
SmsMessage messages=SmsMessage.createFromPdu((byte[]) pdus[0]);
if(messages.getMessageBody().contains("hi")){
abortBroadcast();
}
}
}
Now, from the broadcast receiver, I want to call a function(with parameter), which is within my main activity. Is that possible? If yes, what kind of code should i add in my broadcast receiver ?

Thanks #Manishika. To elaborate, making the Broadcastreceiver dynamic, instead of defining it in the manifest, did the trick. So in my broadcast receiver class, i add the code :
MainActivity main = null;
void setMainActivityHandler(MainActivity main){
this.main=main;
}
In the end of the onReceive function of the BroadcastReceiver class, I call the main activity's function :
main.verifyPhoneNumber("hi");
In the main activity, I dynamically define and register the broadcast receiver before sending the sms:
SmsReceiver BR_smsreceiver = null;
BR_smsreceiver = new SmsReceiver();
BR_smsreceiver.setMainActivityHandler(this);
IntentFilter fltr_smsreceived = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(BR_smsreceiver,fltr_smsreceived);

Pass your Activity's context to BroadcastReceiver's contructor.
public class SmsReceiver extends BroadcastReceiver{
MainActivity ma; //a reference to activity's context
public SmsReceiver(MainActivity maContext){
ma=maContext;
}
#Override
public void onReceive(Context context, Intent intent) {
ma.brCallback("your string"); //calling activity method
}
}
and in your MainActivity
public class MainActivity extends AppCompatActivity {
...
public void onStart(){
...
SmsReceiver smsReceiver = new SmsReceiver(this); //passing context
LocalBroadcastManager.getInstance(this).registerReceiver(smsReceiver,null);
...
}
public void brCallback(String param){
Log.d("BroadcastReceiver",param);
}
}
hope it helps

use this
Intent intent=new Intent();
intent.setClassName("com.package.my", "bcd.class");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

You can't directly call a function in your Activity unless it's a public static method but don't do so. I recommend this:
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = new Bundle();
bundle.putExtraString("ACTION", "stopBroadcast");
// ### put what ever you need into the bundle here ###
Intent intent = new Intent();
intent.setClassName(context, "activity.class");
intent.putExtras(bundle);
context.startActivity(intent);
}
And then from your Activity's onCreate() get Bundle and take your actions as needed.

It's a little bit late, but nobody mentioned it.
There is no need for passing activity.
As #faizal specifies, IntentService is started from MainActivity, so, context in onReceive() is already instance of MainActivity.
It is enough to write smth like this:
#Override
public void onReceive(Context context, Intent intent) {
if(context instanceof MainActivity) {
MainActivity activity = (MainActivity) context;
}
}

Related

How to pass data from BroadcastReceiver to Activity without in onCreate()

I have a serious issue about passing data from BroadcastReceiver to an Activity. Let see my issue carefully. I have a class PhoneStateReceiver extends BroadcastReceiver that used to received an incoming phone.
public class PhoneStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
The incoming phone will be sent to an Activity, called ReceiverActivity. The ReceiverActivity receives the incoming phone and sends it to a server via a socket connection. The socket connection is initialized in the onCreate function. I googled and found server way to pass the data from BroadcastReceiver to an Activity. The common way is that send data via putExtra function and call startActivity. However, the way will call the onCreate again and then connect the socket, draw the UI again. Thus, it is not helpful in my case.
In my goal, If the phone receives an incoming call, it will send the incoming call to the ReceiverActivity. The ReceiverActivity receives the message and calls the send function. Which is the best way to do it? Thank you
The common way to pass data from a BroadcastReceiver to a ReceiverActivity that I used as follows
In PhoneStateReceiver class :
Intent intent_phonenum = new Intent(context, ReceiverActivity.class);
intent_phonenum.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent_phonenum.putExtra("phone_num", incomingNumber);
context.startActivity(intent_phonenum);
In ReceiverActivity class :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connect_socket();
Intent intent = getIntent();
phone_num = intent.getStringExtra("phone_num");
send(phone_num);
}
Simple without any third party libs.
Make sure BroadcastReceiver must be registered and also unregistered on OnPause().
You have to do two thing
Register a receiver in you activity like below.
public class MainActivity extends Activity {
Context context;
BroadcastReceiver updateUIReciver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
IntentFilter filter = new IntentFilter();
filter.addAction("service.to.activity.transfer");
updateUIReciver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//UI update here
if (intent != null)
Toast.makeText(context, intent.getStringExtra("number").toString(), Toast.LENGTH_LONG).show();
}
};
registerReceiver(updateUIReciver, filter);
}
}
Now in you service
public class PhoneStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
Intent local = new Intent();
local.setAction("service.to.activity.transfer");
local.putExtra("number", incomingNumber);
context.sendBroadcast(local);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
There is a very simple design pattern you can use here to ease communication between your classes and also decouple your code: publisher/subscriber. My favorite library for this is EventBus:
First, add to your build.gradle file:
compile 'org.greenrobot:eventbus:3.0.0'
Then, create a simple POJO - Plain Old Java Object like this:
public class OnReceiverEvent{
private String phoneNumber;
public OnReceiverEvent(String phone){
this.phoneNumber = phone;
}
public String getPhoneNumber(){
return phoneNumber;
}
}
Next, by making your Receiver class a publisher, and your Activity a subscriber, you should be able to easily pass the information to your activity like this:
//inside your PhoneStateReceiver class when you want to pass info
EventBus.getDefault().post(new OnReceiverEvent(phoneNumber));
Next, inside your activity, simply do this:
//onStart
#Override
public void onStart(){
super.onStart();
EventBus.getDefault().register(this);
}
//onStop
#Override
public void onStop(){
super.onStop();
EventBus.getDefault().unregister(this);
}
Finally, handle the posted data i.e phoneNumber value:
#Subscribe
public void onPhoneNumberReceived(OnReceiverEvent event){
//get the phone number value here and do something with it
String phoneNumber = event.getPhoneNumber();
//display or something?
}
UPDATE
If you have another Event that you want this activity to subscribe to, simply create a method like you did in the first one using the #Subscribe annotation.
#Subscribe
public void onSomeOtherEvent(EventClassName event){
//get the variables here as usual;
}
This is the easiest way to pass the data from your receiver to your activity without having to worry about starting the activity over and over!
I hope this helps and good luck!
So I understand you don't want to recreate your Activity everytime.
In your Intent changing this flag will help you :
intent_phonenum.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
In Intent class if you read method summary of FLAG_ACTIVITY_CLEAR_TOP:
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that activity,
all of the other activities on top of it will be closed and this Intent
will be delivered to the (now on top) old activity as a new Intent. (you can read more ...)
In this case: If your app is running and you have an Activity instance then Intent will not recreate your Activity. But assume that your app is in closed state and when BroadcastReceiver triggered, the Intent will create new Activity because you don't have instance of that Activity.
#Edit :
You can specify special Intent like that in your BroadcastReceiver:
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
Intent i = new Intent("mycustombroadcast");
i.putExtra("phone_num", incomingNumber);
context.sendBroadcast(i);
}
Then in your Activity inside onCreate() register receiver like that :
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
int incoming_number= bundle.getInt("phone_num");
Log.e("incoming number", "" + incoming_number);
}
};
//then register receiver like that :
registerReceiver(broadcastReceiver, new IntentFilter("mycustombroadcast"));
You can unregister Receiver in onDestroy() : unregisterReceiver(broadcastReceiver);
Also another way is overriding onNewIntent() in your Activity:
#Override
protected void onNewIntent(Intent intent) {
//your intent is here, you can do sth.
super.onNewIntent(intent);
}

How to run function with broadcastreceiver in Android?

I have a function in activity I want to run this function with broadcastreceiver. How can I make this?
public class Myclass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
}
}
This is my broadcastreceiver class I want to run function which is in my activty please tell me with some code how to do this.
If the method you want to execute needs your activity instance, then you can register the broadcast receiver inside your activity, so it can access your activity's state and functions.
In your Activity "onCreate" method:
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("Your Intent action here");
intentFilter.addAction("Another action you want to receive");
final BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
theFunctionYouWantToExecute();
}
};
registerReceiver(myReceiver, intentFilter);
And in your "onDestroy" method:
unregisterReceiver(myReceiver);
Keep in mind that in this case your broadcast receiver has full access to your activity state, BUT it's lifecycle will be conditioned to the activity lifecycle.
Another option you have is to declare your activity method as static, so you can execute it in any part of your application.
You can declare an interface in Myclass and implement it in your MainActivity
public class Myclass extends BroadcastReceiver{
public interface MyClassInterface {
void onMyClassReceive();
}
private MyClassInterface mListener;
public Myclass(MyClassInterface mMyClassInterface) {
mListener = mMyClassInterface;
}
#Override
public void onReceive(Context context, Intent intent) {
mListener.onMyClassReceive();
}
}
Then in your MainActivity:
public class MainActivity implements Myclass.MyClassInterface {
private mMyClass Myclass = new Myclass(this);
#Override
public void onMyClassReceive() {
// Do stuff when Myclass.onMyClassReceive() is called,
// which will be called when Myclass.onReceive() is called.
}
}
You are almost there. Just create your method in the Activity and using Activity's instance call that method. Remember that your method inside your Activity should be not private.
public class Myclass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
new YourActivity().yourFunction();
}
}
If you want to create a static method inside your Activity then
public class Myclass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
YourActivity.yourFunction();
}
}
To trigger the Broadcast, you have to pass an Intent. If you want to trigger it from any Activity then
Intent intent = new Intent();
this.sendBroadcast(intent);
If you want to trigger the Broadcast from a Fragment then
Intent intent = new Intent();
getActivity().sendBroadcast(intent);
I know it's quote naif, but you could call a static method in your activity.
In your activity you declare the method like this:
public static <return_type> yourMethod(<input_objs>){
....
Your code
....
}
In the receiver you can use this function just calling:
YourActivityClass.yourMethod(<input_objs>);
I hope it helped.

Android pass message from IntentService to Activity

I IntentService that I would like to send message to the main Activity it is nested in. I am using a broadcast receiver to broadcast the message I got from the IntentService as such:
public static class ResponseReceiver extends BroadcastReceiver {
public static final String ACTION_RESP = "com.mypackage.intent.action.MESSAGE_PROCESSED";
#Override
public void onReceive(Context context, Intent intent) {
String text;
text = intent.getStringExtra(RegistrationIntentService.PARAM_OUT);
regid = text;
}
}
I have registered the receiver in the Oncreate method of the main Activity. How can I send the "text" in this case? It is weird that regid in this case is null while "text" has the string data I wanted.
you can user result receiver with intent service to get the result into activity or fragment, follow the following links,
http://sohailaziz05.blogspot.in/2012/05/intentservice-providing-data-back-to.html
In your service you do
Intent intent = new Intent();
intent.setAction(yourActionToMatchBroadcastReceiverIntentFilter);
intent.putExtra(RegistrationIntentService.PARAM_OUT, yourText);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
In activity register your BroadcastReceiver in onResume() and unregister it in onPause(). Whenever your activity is active the receiver will receive intents from your IntentService.
EDIT
public static class ResponseReceiver extends BroadcastReceiver {
MapActivity activity;
public ResponseReceiver(MapActivity activity) {
this.activity = activity;
}
#Override
public void onReceive(Context context, Intent intent) {
activity.regid = intent.getStringExtra(RegistrationIntentService.PARAM_OUT);
// do whatever you need here
}
}
When registering, this was what worked for me
IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new ResponseReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
as opposed to
registerReceiver(receiver, filter);
#Override
public void onReceive(Context context, Intent intent) {
final String text = intent.getStringExtra(RegistrationIntentService.PARAM_OUT);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
//access the string text and send it to backend
}
});
}
I hope this will help someone. Sending the string like suggested in the comments didn't work for me. I was getting nullpointerexception at that specific line where I assigned ma.regid = text;

How to Start same activity with different data from Broadcast Receiver?

I have 1 activity that I would like to start at different times with different variables from a Broadcast Receiver.
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase("tv.abcd.v4.ORIGINAL_VIDEO_SCENE")){
channelName = intent.getExtras().getString("com.abcd.Channel");
JSONObject json = new JSONObject(intent.getExtras().getString("com.abcd.Data"));
String incomingScene = json.getString("url");
scene.putExtra("channel", channelName);
scene.putExtra("url", incomingScene);
scene.addFlags(Intent.FLAG_FROM_BACKGROUND);
scene.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
scene.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scene);
}
I have the code to start the activity via Intent and in the activity receiver the extras to make data appear.
Intent intent = getIntent();
sceneUrl = intent.getStringExtra("url");
Log.d("Image.incomingscene.url",sceneUrl);
channelName = intent.getStringExtra("channel");
Log.d("Image.incomingSceneAvatar",networkAvatar);
image = (ImageView)findViewById(R.id.imageView1);
image.setScaleType(ScaleType.FIT_CENTER);
progressBar = (ProgressBar)findViewById(R.id.progressBar1);
Picasso.with(this).load(sceneUrl).skipMemoryCache().fit().into(image, new EmptyCallback() {
});
Now after that I want to start the same activity again from the Broadcast Reciever with different data. So i want the previous activity to get out the way and allow this new instance to start up.
How to accomplish this feat?
register another broadcast receiver from the activity. Then, when you want to kill it, send a broadcast message from the broadcast receiver that you mentioned .
In your broadcastReceiver do something like the following :
public static final String CLOSE_Activity= "com.mypackage.closeactivity";
and in yopr OnReceive method do like the following :
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("HIT OUTGOING");
Intent i = new Intent();
i.setAction(CLOSE_Activity);
context.sendBroadcast(i);
}
then in your activity craete a receviver and register it in the onResume method and unregeister it in the onPause method , like the following :
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(RECEIVER_Class.CLOSE_Activity)) {
finish();
}
}
}
activity onResume method :
#Override
public void onResume() {
registerReceiver(broadcastReceiver, new IntentFilter(RECEIVER_Class.CLOSE_Activity));
}
activity onPause method :
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
Please give me some feedback
Hope that helps .

Is it possible to call putExtras() and getExtra() without starting a new activity?

I'm having two activities which are displayed side by side on one screen through a fragment for each activity. I want to send a String when I click a button on one of the activity, and then the other activity should retrieve the String I sent.
I know that it's possible to do that with the classic way setString() and getString() methods. But I'm wondering, could it be accomplished with putExtra() and getExtra() without opening the targeted activity on a new screen?
You can have both activity's intent as global variable and try using putExtra() from one activity and then getExtra() by another activity.
For Example,
public class activityOne extends Activity
{
public static Intent intent = null;
#Override
protected synchronized final void onCreate(final Bundle savedInstanceState)
{
intent = getIntent();
}
}
public class activityTwo extends Activity
{
public static Intent intent = null;
#Override
protected synchronized final void onCreate(final Bundle savedInstanceState)
{
intent = getIntent();
}
}
Now wherever you want you can access their intent like activityOne.intent,activityTwo.intent followed by null check
You can send the intent as a broadcast and have the receiving fragment register to that broadcast on its start (and unregister on its destroy).
Sending fragment:
Intent intent= new Intent(PARAM_TRANSFER);
intent.putExtra(key, extra);
sendBroadcast(intent);
Receiving fragment:
register:
IntentFilter intentFilter = new IntentFilter(PARAM_TRANSFER);
registerReceiver(mReceiver, intentFilter);
unregister:
try {
unregisterReceiver(mReceiver);
} catch (Exception e) {}
getting the param:
private class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
intent.getExtra(key);
}
}

Categories

Resources