EventBus multiplying messages by count of Activities - java

I'm using greenrobot EventBus and have some misunderstandings how to use it.
In my app, I have 4 activities: MainActivity and 3 other. Each Activity have it's own role in app, and MainActivity holds connection via COM port and sends/receives messages. So, when message is received, it sends via EventBus to current working activity. And when other Activity needs to sent message to COM port, it sending message to MainActivity via EventBus too. Problem is that when I'm working in one activity - all works fine, but when I try to do something in other activities - messages from EventBus are duplicaed. There is more - when I try to work in third activity - message is multiplies by 3 and so on.
Here some code:
public class ManualControl extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//my other code here
}
#Override
protected void onPause()
{
super.onPause();
EventBus.getDefault().unregister(this);
}
#Override
public void onResume()
{
super.onResume();
EventBus.getDefault().register(this);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(MessageEventFromMain event)
{
//code to do when get message from MainActivity
};
private void sendMessage(String messageID, String messageName)
{
EventBus.getDefault().post(new MessageEventFromIntent(messageID, messageName));
}
}
This method I use to send message to another Activity from MainActivity
EventBus.getDefault().post(new MessageEventFromMain(messageFromSerial));
And catch event from other Activities in MainActivity
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventFromIntent(MessageEventFromIntent event)
{
//code to do when get message from intent
}
As you can see, I'm unregistering onPause() and registering onResume(), but when I'm closing this activity and starting it again messages are duplicating.
Example:
1st use:
55017031011_TURN_STRAIGHT27
2nd use:
55017031011_TURN_STRAIGHT2755017031011_TURN_STRAIGHT27
I have readed gitHub issues, but not found any answer.
And sorry for mistakes.

Unregister MainActivity from MessageEventFromIntent event after the activity is closed.

Related

Notification Listener - onNotificationPosted doesn't work

I'have tried all kind of solutions and code but any of this solutions worked for me, and I don't know why. Please help me.
My MainActivity code is:
if(isNotificationServiceEnabled())
{
Intent i= new Intent(this,NotificationsService.class);
i.putExtra("command", "get_status");
startService(i);
}
else
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
Now I'm just tryng to check if the service read a nostification posted, but from log i can only see that it enters in onCreate method but no in onNotificationPosted.
This is the code for my service class:
public class NotificationsService extends NotificationListenerService {
#Override
public void onListenerConnected(){
Log.d(TAG, "Connected");
}
#Override
public void onNotificationPosted(final StatusBarNotification sbn){
Log.d(TAG,"got it");
}
I have tried also solutions with broadcast service , but it still doesn't work.
Thanks.
I have found the solutions. In my code I had some problems, but then I tested other code about notification listener in an other project, and It worked. So then I modify my code and now it works.
About notification lisener You don't need to launch the service, because when you launch the app the service is launched. So I just made this changes to my code:
Main
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!isNotificationServiceEnabled())
{
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
And in the service I just put the log code to write in debug the notification package.
Instead I got that broadcast are just used to exchange the data between service and my activity, for example to write the notifications in a textview.

How can i do something before app is closed? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have made an App in android in which i have a TCP Client but now i want to send a message to the server only when the app is going to be closed, i've trying to add the openConnection (opening connection with TCP Client) and sendMessage (Sending message to the TCP server) action in onDestroy method but that didn't worked.
The TCP Client i've used is in this guide, actually i need to send this message for communicate the server that the communication with the device is closed and send message "Device is Offline" and just then close the app.
Method 1: You can use ActivityLifecycleCallbacks to achieve this. There's an example with some logs below.
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private int mVisibleCount;
private boolean mInBackground;
#Override public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override public void onActivityStarted(Activity activity) {
mVisibleCount++;
if (mInBackground && mVisibleCount > 0) {
mInBackground = false;
Log.i(TAG, "App in foreground");
}
}
#Override public void onActivityResumed(Activity activity) {
}
#Override public void onActivityPaused(Activity activity) {
}
#Override public void onActivityStopped(Activity activity) {
mVisibleCount--;
if (mVisibleCount == 0) {
if (activity.isFinishing()) {
Log.i(TAG, "App is finishing");
} else {
mInBackground = true;
Log.i(TAG, "App in background");
}
}
}
#Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override public void onActivityDestroyed(Activity activity) {
}
});
}
public boolean isAppInBackground() {
return mInBackground;
}
public boolean isAppVisible() {
return mVisibleCount > 0;
}
public int getVisibleCount() {
return mVisibleCount;
}
}
Method 2: There's another method using Service to detect if application is terminated. See link
Following method call on diff action
Minimize the Application using home button --> this calls
onPause()
onStop()
Remove the app from Task Manager ->
then onDestroy() is called for that MainActivity (launcher).
So Make an parent Activity suppose named BaseActivity and override its
onPause(), onDestroy() and onStop() method and call your
implementation from here and then extend this Activity from your
another Activities
You should not rely on the onDestroy method. As per the official android documentation it is not called always.
Try to put the same code in the onStop() method of your activity.
Additionally you can have a parent activity which is extended by all other activities.
You can then override the onPause() and onStop() method in your particular child activities and handle the specific scenarios.

Add data to recyclerView from Sqlite in realtime?

I've made an app that is receiving some data from a TCP Client to my TCP Server that store the data in SQlite DB, and actually i've made a recyclerView where to visualize all that data but now my issue is what i'm trying like 2 weeks to refresh the recyclerView in real Time, i mean if a TCP Client will send a new package to my TCP Server and if i'm in the activity with the recyclerView the data have to be added dynamically.
I will also accept any type of tips and suggestions on how to improve my app.
Actually it's my 1st app i've ever created in Android.
HERE you can find my Server(TCPServer),RecyclerViewAdapter,Adapter(constructor),allert.java(class where i invoke the RecyclerViewAdapter.
Hope someone will be able to help me and ill be very grateful.
Try sending broadcast method. Here are the steps :
Make a inner class that extends BroadcastReceiver in your activity.
private class ExampleBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//do stuffs here, e.g. getting extras from intent
}
Declare a instance of the class outside any methods.
public class MainActivity extends AppCompatActivity {
private ExampleBroadcastReceiver exampleBroadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
//stuffs
}
}
Override onResume method. Initialize the instance you just made in this method. Then, register it with a intent-filter. This will make sure that your broadcast receiver ready when user open the activity.
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("com.example.MainActivity");
exampleBroadcastReceiver = new ExampleBroadcastReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(exampleBroadcastReceiver, filter);
}
Override onPause method and unregister your receiver.
#Override
protected void onPause() {
super.onPause();
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(exampleBroadcastReceiver);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("Receiver not registered")) {
// unexpected, re-throw
throw e;
}
Make sure you use ArrayList for dynamic data.
Whenever you receive data from server, after you store them in your database, send a broadcast with extras contains data you want to display in your activity.
EDITED
I registered the receiver using an instance of LocalBroadcastManager.

How to display a toast message in only one activity?

In an application I am developing I have some code that attempts to submit information to the internet. If the connection can not be made, I pop up a toast message instructing the user to check the network connection.
Toast.makeText(getApplicationContext(), "Check network connection.", Toast.LENGTH_SHORT).show();
The problem I have is the toast message comes up no matter what the user is looking at! Even if the user is in a different app and my app is running in the background! This is not the desired behavior as I send a notification to the user if network activity fails. I only want the toast message to appear if the user is in the activity that is generating the network activity. Is there a way to do this?
If this is not possible my idea was to just put some kind of visual element in my activity - rather than display a toast message.
Thank You!
You can use a boolean class member in order to keep track of activity state changes.
public class YourClass extends Activity {
private boolean mIsResumed = false;
#Override
public void onResume() {
super.onResume();
mIsResumed = true;
}
#Override
public void onPause() {
super.onPause();
mIsResumed = false;
}
public boolean isResumed() {
return mIsResumed;
}
}
Then you can use something like this:
if (isResumed()) {
//show Toast
}
Use a dynamic BroadcastReceiver. Your background service will broadcast an Intent when something happens. All of your app's activities will register a dynamic BroadcastReceiver which will listen for these events. When such event occurs it will show a toast. When none of your activities are running nothing will happen.
Inside your service
public static final ACTION_SOMETHING = BuildConfig.APPLICATION_ID + ".ACTION_SOMETHING";
public void doSomething() {
// ...
// Show toast if app is running. Or let the app react however you please.
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(ACTION_SOMETHING));
// ...
}
Of course you can put additional information in the Intent as extras and access them in the BroadcastReceiver.
Inside your activities
private final IntentFilter onSomethingIntentFilter = new IntentFilter(MyService.ACTION_SOMETHING);
private final BroadcastReceiver onSomething = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// This check seems redundant but it's not. Google it.
if (MyService.ACTION_SOMETHING.equals(intent.getAction()) {
// Show toast here.
}
}
};
public void onResume() {
super.onResume();
// Start listening for events when activity is in foreground.
LocalBroadcastManager.getInstance(this).registerReceiver(onSomething, onSomethingIntentFilter);
}
public void onPause() {
super.onPause();
// Stop listening as soon as activity leaves foreground.
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(onSomething);
} catch (IllegalArgumentException ex) {}
}
You may want to pull this code to a common activity parent, a BaseActivity, so you don't repeat yourself.
This is a common case of Provider-Subscriber pattern. Another implementation would be an EventBus.
Keeping it simple, try adding a boolean flag in Activity and set its value as true in onResume & false in onPause. Then display the toast if the boolean flag is true.

How do I return data from a GCMListenerService to an Activity using a ResultReceiver?

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 .

Categories

Resources