How to call activity class method from fcm service.
I already tried this way Calling activity class method from Service class
but in fcm service onBind method is final so we can not overwrite, so any other way to call activity class method from fcm service.
for reference some code how to implement fcm.
public class FCMListenerService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage message) {
}
}
When my activity is running and fcm notification came then i want to update code? is there any way to handle this requirement ?
I think you have to try with BroadcastReceiver. This is how you send a message from your FCMListenerService:
public class FCMListenerService extends FirebaseMessagingService {
public static final String INTENT_FILTER = "INTENT_FILTER";
#Override
public void onMessageReceived(RemoteMessage message) {
Intent intent = new Intent(INTENT_FILTER);
sendBroadcast(intent);
}
}
And then you can try to catch it this way, using broadcast receiver in your activity:
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUi();
}
};
Do not forgot to register / unregister your receiver in onCreate() / onDestroy() method from your activity.
onCreate()
registerReceiver(myReceiver, new IntentFilter(FCMListenerService.INTENT_FILTER));
onDestroy()
unregisterReceiver(myReceiver);
Try this Suppose you want to call method of MainActivity;
Make static variable Context context and initialise in onCreate() of MainActivity.
and make the method static which you want to call in MainActivity say
public static void updateUi()
{
// code to update Ui
}
then call from service like this:-
((MainActivity)MainActivity.context).updateUi();
Update:
if you want to perform in multiple activities then you can this method and handle the logic in this updateUi() method
Related
I would like to update my UI from a different class. I am familiar with runOnUiThread() method, but don't know how to implement it in this scenario?
public class UploadAct extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload);
}
//my code and functions would go here
}
Then, my UploadData class
public class UploadData extends UploadAct {
public void doSomethig(){
printThis("I want to print this message to the UI");
}
public void printThis(String messsage) {
final String mess = message;
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),mess,Toast.LENGTH_LONG).show();
// I want this to display on the main thread
txt_upload.setText(mess);// and this also
}
});
}
}
Use BroadcastReceiver
// define a Broadcast Intent Action in String resources
<string name="broadcast_id">MY_BROADCAST_ID</string>
// register receiver in constructor/onCreate()
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter myIntentFilter = new IntentFilter();
myIntentFilter.addAction(context.getString(R.string.broadcast_id));
context.registerReceiver(myBroadcastReceiver, myIntentFilter);
// place your BroadcastReceiver in MainActivity, your UploadData class
public class MyBroadcastReceiver extends BroadcastReceiver {
public MyBroadcastReceiver(){
super();
}
#Override public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Broadcast received");
if(intent.getAction() != null && intent.getAction().equals(context.getString(R.string.broadcast_id)) ){
// do something
}
}
}
// send Broadcasts from where you want to act, your UploadAct class.
Intent intent = new Intent();
intent.setAction(context.getString(R.string.broadcast_id));
context.sendBroadcast(intent);
Log.d(TAG, "Broadcast sent.");
// you can unregister this receiver in onDestroy() method
context.unregisterReceiver(myBroadcastReceiver);
You can also use an interface to update your UI as a listener.
First, Create an interface
public interface UpdateTextListener {
void updateText(String data);
}
Then, Call its method in your UploadData class
public class UploadData extends UploadAct {
UpdateTextListener listener;
public void doSomethig(){
listener.updateText("data to be loaded");
}
}
Then, Update your UploadAct by listening to this method
public class UploadAct extends MainActivity implements UpdateTextListener {
#Override
public void updateText(String data) {
textview.setText(data);
}
}
First of all - there is no such thing like UI of some class. There are activities that can have handles to UI widgets (ex TextView). If you want to make some changes to UI from your UploadData class you have to pass somehow reference to this class. Possibly by constructor:
public class UploadData extends UploadAct{
private TextView txt_upload;
public UploadData(TextView tv)
{
txt_upload = tv;
}
public void doSomethig(){
printThis("I want to print this message to the UI")
}
public void printThis(String messsage) {
final String mess = message;
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),mess,Toast.LENGTH_LONG).show();// I want this to display on the main thread
txt_upload.setText(mess);// and this also
}
});
}
}
I assume that you create DataUpload in your MainActivity.
Everyone use so much library to be trendy as they forget built in functions in Android :)
For sure isn't any hard thing to use AsyncTask, beside it provides the doInBackground function it has the https://developer.android.com/reference/android/os/AsyncTask.html#publishProgress(Progress...) function too, what you have asked for.
Just create a class (UploadTask) which extends AsyncTask and override 1-2 function.
I have a GCMListenerService that will be used for push notifications from my server to my client. I need this listener to interrupt a thread that is running in the Presenter (my project is structured using the MVP pattern). However, I do not know how to pass a result receiver to the Service because I don't think I can overrride onStartCommand(). The other option would be a LocalBroadCast Manager, but I'd like the message to go through even when the activity is paused, so I don't think a local broadcast manager would work.
create abstract BroadcastReceiver as follows :
public abstract class DataReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
onDataRefresh(intent);
}
protected abstract void onDataRefresh(Intent intent);
}
and use it in the activity as follow:
class Acb extends Activity{
onCreate(){
DataReceiver data = new DataReceiver(
#Override
protected void onMenuItemUpdate(Intent intent) {
});
}
}
whatever the data you passed using sendBroadcast(intent); ,that data you can access here .
I have a Main activity and after click on button I start thread (but the thread is hidden in library and I have only callback in Main activity.
Now I want to start another activity (call A) where I want to put results from the thread.
Below is simplified code:
public class Main extends Activity {
XManager.ResultsCallback xResultsCallback = new XManager.ResultsCallback() {
// the method is called every 10 sec.
#Override
public void onResult(ArrayList<String> texts) {
}
};
XManager xManager = new xManager(xResultsCallback);
View.OnClickListener onClick = new View.OnClickListener() {
#Override
public void onClick(View arg0) {
XManager.start();
Intent i = new Intent(Main.this, A.class);
startActivity(i);
}
};
}
I want to update the content of A activity each time when onResult() method is called. How to do that?
Use LocalBroadcastManager,
In your Main Activity create function :
private void sendResult() {
Log.d("sender", "Broadcasting message");
Intent intent = new Intent("custom-event-name");
// You can also include some extra data.
intent.putExtra("message", "This is my result!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
and add BroadcastReceiver in your A Activity
private BroadcastReceiver onResult= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("jazzy","onReceive called");
}
};
add on OnCreate
#Override
public void onCreate(Bundle savedInstanceState) {
// Register to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
add onDestroy
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
I have a suggestion that you should do as follows:
Start Your Activity A on button click
Inside Activity A declare your XManager instance with a callback present in A itself
Then start your XManager as XManager.start(); that way you would be getting all the callbacks in your desired activity.
Have a great day!
I think if you want to decouple the logic, beside you can use the Android BroadcastReceiver, the another flexible choice is to use the Bus
And you can integrate it with gradle easily
dependencies {
compile 'com.squareup:otto:+'
}
I'm relatively new to Android,
I have read related articles on detecting network connectivity changes and have implemented this BroadcastReceiver subclass, made the necessary additions to AndroidManifest.xml and I receive the requisite state change broadcasts as expected:
public class NetworkStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
Question is: how can I receive or forward these notifications in/to my Activity subclasses? Apparently creating an instance of NetworkStateReceiver in my Activity subclass and overriding onReceive there doesn't do the trick.
Thanks in advance for any pointers...
Edit:
I ended up broadcasting an Intent from onReceive above like so:
Intent target = new Intent(CONNECTIVITY_EVENT);
target.putExtra(CONNECTIVITY_STATE, networkInfo.isConnected());
context.sendBroadcast(target);
And receiving that in my Activity like so:
#Override
protected String[] notifyStrings() {
return ArrayUtils.addAll(super.notifyStrings(), new String[] {NetworkStateReceiver.CONNECTIVITY_EVENT});
}
#Override
protected void notifyEvent(Intent intent, String action) {
super.notifyEvent(intent, action);
if (action != null) {
if (action.equalsIgnoreCase(NetworkStateReceiver.CONNECTIVITY_EVENT)) {
boolean isConnected = intent.getBooleanExtra(NetworkStateReceiver.CONNECTIVITY_STATE, true);
// Do something...
}
}
}
I would recommend using either
1) An interface approach. So declare an interface that has a networkChanged() method, and have the class which owns this BroadcastReceiver keep a list of classes who want to be notified of network changes with a local List<InterfaceName>
2) Skip the interface creating and use a subscription utility. My two favorites are
https://github.com/greenrobot/EventBus
and
https://gist.github.com/bclymer/6708819 (smaller, less used, also disclaimer: I wrote this)
With these you would create event classes with properties, and then subscribe and post instances of those classes.
In your activity
#Override
public void onCreate() {
...
EventBus.getInstance().subscribe(this, MyType.class);
}
#Override
public void onDestroy() {
...
EventBus.getInstance().unsubscribe(this, MyType.class);
}
#Override
public void newEvent(Object event) {
if (event instanceOf MyType) {
// do stuff
}
}
And then in your BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent) {
EventBus.post(new MyType(true));
}
Example MyType
public class MyType {
public boolean networkEnabled;
public MyType(boolean networkEnabled) {
this.networkEnabled = networkEnabled;
}
}
This examples use the 2nd subscription utility (mine).
What i am trying to do is to pass a reference to the mainactivity to another class and use it.
when i first pass the reference it is not null. but later when i use it in an event handler it becomes null.
here is the code:
public class MainActivity extends MapActivity implements SmsReceivedListener {
SmsReceiver smsreceiver = new SmsReceiver();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
smsreceiver.setSmsReceivedListener(this);
}
public void drawme() {
// do smth
}
#Override
public void onSmsReceived(String id, String lon, String lat) {
Toast.makeText(this, "SMS delivered", Toast.LENGTH_LONG).show();
}
}
The other class where I obtain the reference:
public class SmsReceiver extends BroadcastReceiver {
private SmsReceivedListener listener;
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
#SuppressLint("NewApi")
#Override
public void onReceive(final Context context, final Intent intent) {
// Here it is NULL
if(listener!=null)
listener().onSmsReceived(carNumber, lon,lat);
}
public void setSmsReceivedListener(SmsReceivedListener mainActivity) {
//It is no null when I first set the object here
listener = (mainActivity);
}
}
It will only "become" null if you
set it to null
use it in a way which is not thread safe and you are reading in a different thread to setting
you are using the same field, but in a different object.
You are not registering the SmsReceiver, therefor i guess the following :
The SmsReceiver is registered in the Manifest. Therefore, an instance of the receiver is created by the system when the broadcast is detected, and it is not the same instance as the one you create.
Suggestion : register the receiver in the activity, not in the manifest.