How to navigate to a fragment from a class extending BroadcastReceiver using the new Navigation Architecture Components - android

I am having my Broadcast Receiver which is supposed to scan incoming messages and pass the originating address and message to a new fragment using bundles and using the new Navigation Architecture Components and navController. I am stuck because i cant find a view in the Broadcast Receiver. Here is what i have tried so far.
public class SimpleSmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle pudsBundle = intent.getExtras();
Object[] pdus = (Object[]) pudsBundle.get("pdus");
SmsMessage messages = SmsMessage.createFromPdu((byte[])pdus[0]);
Bundle bundle = new Bundle();
bundle.putString("MessageNumber", messages.getOriginatingAddress());
bundle.putString("Message", messages.getMessageBody());
Navigation.findNavController(context).navigate(R.id.nav_otp_fragment, bundle);
}
}
I am getting the error Required Type: View Provided: Context

BroadcastReceivers are not UI components. You can't do anything with the UI in a BroadcastReceiver. If your BroadcastReceiver has a reference to your Activity then it can call a method in the Activity (with data as arguments) so that the Activity can then create the Fragment and do whatever else is necessary.

Put your code inside runOnUiThread block
runOnUiThread {
// do something for UI
}

Related

How to implement callback listener in BroadcastReceiver onReceive on notification tap?

I am creating an app that sends a notification when an SMS is received. When the notification is tapped, it opens the MainActivity and shows the received SMS. The problem is, when the app is closed and an SMS is received, the mListener inside the onReceive method of BroadcastReceiver class produces a null pointer exception (NPE). Logs show the error: "Attempt to invoke interface method 'void com.example.smsread.listener.SmsListener.messageReceived(java.lang.String)' on a null object reference".
What can I do so that the control can be passed to the activity from onReceive?
I can perform the action sending notification within the onReceive but doesn't seem appropriate. I wish to pass the message to the interface and let the activity implement it.
SmsReceiver.java
public class SmsReceiver extends BroadcastReceiver {
//interface
private static SmsListener mListener;
public static void bindListener(SmsListener listener) {
mListener = listener;
}
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Object[] pdus = new Object[0];
if (bundle != null) {
pdus = (Object[]) bundle.get("pdus");
}
StringBuilder messageBody = new StringBuilder();
if (pdus != null) {
for (Object pdus1 : pdus) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus1);
messageBody.append(smsMessage.getMessageBody());
}
}
//Pass the message text to interface
mListener.messageReceived(messageBody.toString()); // mListener here is null
}
}
I expect the mListener to pass the control to the MainActivity where the interface is implemented but mListener is found to be null. Please help as to what changes have to be done so that mListener points to the MainActivity.
If there is a better way to implement the scenario I wish to implement, suggestions are more than welcome.
Thanks in advance :)
You are trying to call function of an Activity that was already destroyed.
If you want to communicate with your activity from a BroadcastReceiver, Use Intent.
Create a new Intent with your Activity as target and send the message as as Extra in Intent Extras Bundle.
In your Activity, you can set launchMode to singleInstance or singleTask in your manifest file. This means that the Intent if sent and your Activity is already open, it will call onIntent function in your activity where you will call the listener function.
android:launchMode="singleInstance"
#Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
processDataFromBroadcast(intent);
}
Be sure to read about launch modes and singleInstance to fully understand what it means or you might get unexpected behavior:
https://developer.android.com/guide/components/activities/tasks-and-back-stack#ManifestForTasks

How to send data from BroadcastReceiver to Fragment in android

I am trying to make an chatting app.I have a SlidingDrawer Activity and it has many fragments and among which ChatFragment is one.Now when i am sending message to my friend , i have a Chatting Window and if any message comes from GCM service and i am in ChatFragment then this message will go to that Fragment and update the listview as i want to update the chatWindow when any message comes while chatting Now I tried to do like below.
GcmIntentService :
public class GcmIntentService extends IntentService {
public GcmIntentService() {
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (extras != null && !extras.isEmpty()) { // has effect of unparcelling Bundle
// Since we're not using two way messaging, this is all we really to check for
if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
Logger.getLogger("GCM_RECEIVED").log(Level.INFO, extras.toString());
showToast(extras.getString("message"));
Intent sendData = new Intent("chatupdater");
sendData.putExtra("msg", extras.getString("message"));
LocalBroadcastManager.getInstance(this).sendBroadcast(sendData);
Log.i("chat","i am in GCMIntentService");
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
Here i am starting a broadcastreceiver in onHandleIntent().
ChatBroadCastReceiver:
public class ChatBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("chat","I am in ChatBroadCastReceiver");
String msg = intent.getStringExtra("msg");
Log.i("chat",msg);
//Intent data = new Intent("chatupdater");
//Intent data = new Intent("chatupdater");
//data.putExtra("key","data");
//data.putInt("fragmentno",1); // Pass the unique id of fragment we talked abt earlier
//context.sendBroadcast(intent);
}
}
This is my ChatBroadCastReceiver class and if any message comes it successfully receives at the onReceive() method.Now i want to send this message to the Fragment.What i tried , i registered the Fragment with it and tried to get the same data at the onReceive() of ChatFragment.But it didn't call.I tried to see by logging.
public class ChatFragment extends Fragment {
//ChatBroadCastReceiver mReceiver;
private EditText et_chat;
Bundle mailData;
String caller_mail;
private ListView chatListview;
private ChatWindowAdapter chatWindowAdapter;
private List<ChatSession>PreviousChatSession;
private List<ChatInfo> chatListItems;
Button chat_send;
public ChatFragment() {
}
public BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("chat","I am in BroadCastReceiver");
String msg = intent.getStringExtra("msg");
Toast.makeText(getActivity(),msg,Toast.LENGTH_LONG).show();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReceiver = new ChatBroadCastReceiver();
//getActivity().registerReceiver(new ChatBroadCastReceiver(),new IntentFilter("chatupdater"));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(new ChatBroadCastReceiver(),new IntentFilter("chatupdater"));
Log.i("chat", "I am in onCreate");
}
Now how can i get the message which i got in the Broadcastreceiver to the onReceive() of ChatFragment??
Try this
Create an interface which will have a method like this.
public interface DemoListener {
public void receiveMessage(String message);
}
Now implement this in your fragment and register the listener in BroadcastReceiver, now as soon as your broadcast receiver receives any message it will be available to your fragment via this Listener.Hope this helps.
To Register your Broadcast You are using:
mReceiver = new ChatBroadCastReceiver();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mReceiver ,new IntentFilter("chatupdater"));
So you will Only receive Broadcast on ChatBroadCastReceiver class. Because mReceiver is a Instance of ChatBroadCastReceiver class.
Now to Receive broadcast Message on anonymous class that you have created in your ChatFragment you need to register that like below code. Where mReceiver is a Instance of anonymous BroadcastReceiver class that you have implemented in your ChatFragment class.
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mReceiver ,new IntentFilter("chatupdater"))
To Receive Broadcast Message Both on ChatFragment and ChatBroadCastReceiver you need to register broadcast receiver twice.
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mReceiver ,new IntentFilter("chatupdater"))
ChatBroadCastReceiver mChatBroadCastReceiver = new ChatBroadCastReceiver();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mChatBroadCastReceiver ,new IntentFilter("chatupdater"))
Hope this answer will help you to understand your problem.

send data from a broadcast to an activity . how to do send?

how to send data from a broadcatReceiver to an activity in android as saying catch the received SMS and send the SMS (is the data) to the activity its my first time that i work with broadcatReceiver so can anyone help me i will appreciate any help.
i read several tutorials about the data transferring that have some steps :
create a class that extends activity
create a class that extends broadcastReceiver
but i did not know how is the communication between these 2 classes.
I would do something like that:
public class YourActivity extends Activity
{
private Handler handler = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.id.main_layout);
this.handler = new Handler() {
#Override
public void handleMessage(Message msg)
{
SmsMessage sms = (SmsMessage) msg.obj;
String senderNumber = sms.getOriginatingAddress();
}
};
// Register a new receiver that will trigger on SMS_RECEIVED event
IntentFiler filer = new IntentFilert("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mSmsReceiver, filter);
}
#Override
protected void onDestroy()
{
super.onDestroy();
// Unregister the receiver
unregisterReceiver(mSmsReceiver);
}
private mSmsReceiver = new BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle bundle = intent.getExtras();
if (bundle == null || bundle.containsKey("pdus") return;
// Decode the message
SmsMessage sms = SmsMessage.createFromPdu((byte[]) pdus[0]);
// Notify the activity with the message
Message msg = new Message;
msg.obj = sms;
YourActivity.this.handler.sendMessage(msg);
}
};
}
The receiver and the Activity are separate entities and do not usually interact directly. Imagine the following scenario: you have a receiver getting lots of SMS messages, and every time you get one, you launch an Activity to show the message received. Wouldn't this be very annoying to the user?
I'd says that you can interact with the user by creating a Notification and if the user clicks on it, then you open the Activity you want to show the details.
As how to pass the data to the Activity (hopefully using a notification first), given that SMS messages are short in nature you can just put the data in the Intent.
How to set a Notification to launch an Activity: see Open application after clicking on Notification

How can I use SMS broadcast receiver in for different Activity

I have SMS broadcast Receiver Activity. I am using it for one screen(Monitor).
I also want to use this for another screen(Registration). I have different activities for Monitor and Registration. How can I use this?
Currently I am able to use the BroadcastRecevier only for Registration screen
public class SMSReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent)
{
Bundle bundle=intent.getExtras();
Object[] messages=(Object[])bundle.get("pdus");
SmsMessage[] sms=new SmsMessage[messages.length];
for(int n=0;n<messages.length;n++){
sms[n]=SmsMessage.createFromPdu((byte[]) messages[n]);
}
for(SmsMessage msg:sms){
// RegActivity.updateMessageBox(msg.getMessageBody());
MonitorMenu.updateMessageBox(msg.getMessageBody());
}
}
}
Broadcast Receiver will called only when any msg is broadcasted so your receiver will be called when sms will be received.. so whenever your receiver is called save the data in somewhere and use it wherever you want to use..

Android Broadcast from Service To Activity

I am trying to send a Broadcast from a service out to an Activity. I can verify the broadcast is sent from within the service, but the Activity doesn't pick up anything.
Here is the relevant service code:
Intent i = new Intent(NEW_MESSAGE);
i.putExtra(FriendInfo.USERNAME, StringUtils.parseBareAddress(message.getFrom()));
i.putExtra(FriendInfo.MESSAGE, message.getBody());
i.putExtra("who", "1");
sendBroadcast(i);
And the receiving end in the activity class:
public class newMessage extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equalsIgnoreCase(IMService.NEW_MESSAGE)){
Bundle extra = intent.getExtras();
String username = extra.getString(FriendInfo.USERNAME);
String message = extra.getString(FriendInfo.MESSAGE);
String who = extra.getString("who");
}
}
}
The BroadcastReceiver is defined within an Activity. I am registering the receiver in the onCreate method of the Activity, not in the Manifest file.
I'm stumped as to why it won't rec. anything.
Any insight?
EDIT
Registering takes place as follows:
registerReceiver(messageReceiver, new IntentFilter(IMService.NEW_MESSAGE));
Where "messageReceiver" is defined as
private newMessage messageReceiver = new newMessage();
IMService.NEW_MESSAGE is merely a string = "NewMessage"
I'm not sure if it is specific to the set up, or if it is a fix in general, but moving the register/unregister to the onResume/onPause _respectively_ and not registering in the onCreate solved the problem for me.
Try this two things:
Use manifest file to register receiver(but it barely helps)
Try make your Receiver a regular class, not inner one.
Inner class broadcast receiver will not be able to handle broadcast(means it unable to locate that class ).
So make it as a separate class
Definitely it will work.

Categories

Resources