update adapter data while activity is paused - java

i have an adapter in activity and its arrayList
private ArrayList<String> data = new ArrayList<>();
and i have brodcastReciver too when i get data i add it to the ArrayList data
data.add("bla bla bla"); // brodcast data
and update adapter
but my adapter not updated when activity its paused and i missed the brodcast data
so what the solution for this i just made some search and found this answer but he did't share the idea
my app idea its chatting app with sqlite of Course and the problem i missed the BrodcastEvent when activity its paused and get the data from sqlite every time activity its resumed i see it as bad idea

The BroadcastReceiver would receive event without activity start or resume If register it in your manifest.
<receiver android:name="YourReceiver" >
<intent-filter>
<action android:name="android.intent.action.YourAction" />
</intent-filter>
</receiver>
Another issue, how BroadcastReceiver notify message adapter.
You could define a singleton object as observer register manager. If activity start, it register itself, and BroadcastReceiver notify it when receive new message.
BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent) {
...
SingletonRegister.getInstance().addMessage("bla bla bla");
}
Activity
protected void onCreate(Bundle savedInstanceState) {
...
SingletonRegister.getInstance().observe(this);
}
#Override
public void update(String message) {
data.add(message);
}
If activity don't start, activity would not get notified because of not registered. In order to ensure receive all messages, activity need actively request last messages after register.
Activity
protected void onCreate(Bundle savedInstanceState) {
...
SingletonRegister.getInstance().observe(this);
requestMessageFromServer();
}

Related

LocalBroadcastManager not receiving messages correctly

I have a, what I thought was a, simple task. I have a list of achievements in a recyclerView in my MainActivity. Clicking on one of the achievements launches the AchievementDetailActivity. You do an action in the AchievementDetailActivity and it completes the achievement. When that happens, I need the thumbnail on the MainActivity to be the achievement icon and not the locked icon. What I thought was I could just use the LocalBroadcastManager to send and receive messages from one activity to another, but that isn't working. From everything I have read you are supposed to unregister the listener in your activity onPause and onStop lifecycle methods, however, if you unregister the listener in the onPause of MainActivity, it gets unregistered when the AchievementDetailActivity starts and nothing gets delivered to the MainActivity. I don't understand how you can use LocalBroadCastManager with receivers to send information between activities when they get unregistered as soon as you start a new activity. The following example shows it unregisters as soon as the second activity is started, so the first activity will never get the broadcast...
public class MainActivity extends AppCompatActivity {
public static final String ACTION = "update";
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MAIN ACTIVITY", "RECEIVED EVENT");
}
}
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver), new IntentFilter(ACTION));
}
public void onPause() {
Log.d("MAIN ACTIVITY", "REMOVING LISTENER");
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
//.. The rest of MainActivity
}
public class SecondActivity extends AppCompatActivity {
#Override
public void onStart() {
super.onStart();
//initialize view and such
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
Intent intent = new Intent(MainActivity.ACTION);
intent.putExtra("Something", "somewhere");
manager.sendBroadcast(intent);
}
)};
}
If you run the above, obviously with the buttons and such, you will get a message that shows it unregisters the listener as soon as SecondActivity starts and the MainActivity will never get the message it is supposed to get when you click a button on the second activity.
Is there a way to send information from activity to activity, or because of the lifecycle events is that not possible? Everything I read said LocalBroadcastManager was the right way to do it, but it gets unregistered so, how can it? Please help, this is driving me nuts. Thank you.
If you want to use your LocalBroadcastManager to fetch results, do not unregister in onPause, in which case must to unregister in onDestroy().
If you startAvtivity only to fetch some results, it is a good way to startActivityForResult.
Its not a great idea to use LocalBroadcastReceiver for this purpose. Use startActivityForResult instead. Follow this Official doc for implementation details.
The reason its not wokring is:
You are registering the receiver in onStart and unregistering it in onPause(). When your second activity is shown, onPause () will be called as a result the BroadcastReceiver is unregistered.
Its not a great idea to keep it registered since it would lead to memory leaks.

Sending a push notification only when app is in background

I use NotificationManager, NotificationChannel and NotificationCompat.Builder to display a push notification when an event is triggered, no online Firebase.
The push notification appears when my app is in foreground and background, but it only should appear when my app in the background.
I have 2 Activities where just only 1 knows the class, where the push notification is created. I could just set a variable that shows if my Activity is in foreground or not (with onResume and onPause), but if my other Activity starts the Activity with the notification trigger class is set in background and therefore I can't use this method. I would need to know if the whole app is in foreground or not, but I didn't find a good solution for that problem.
So is there an other way to display push notifications just when my whole app is in background?
I think you have FCMListenerService to receive your push notification as a background service. The Service should have the following declaration in the manifest file.
<service android:name=".Service.FCM.FCMListenerService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Now you can pass the context of this service alone to check if the application is in foreground or in background. The function for checking if the application is foreground is following.
private static boolean isForeground(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.getRunningTasks(1);
ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
return componentInfo.getPackageName().equals(Constants.ApplicationPackage);
}
Hence, in your onMessageReceived function you need to check if the application is in foreground and do not create the notification in the status bar.
public class FCMListenerService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage message) {
if(!isForeground(this)) createNotification();
}
}
Hope that helps!
So I found a proper and very good solution for this problem.
According to this answer: https://stackoverflow.com/a/42679191/6938043
Application.ActivityLifecycleCallbacks
public class MainActivityChats extends AppCompatActivity implements Application.ActivityLifecycleCallbacks
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getApplication().registerActivityLifecycleCallbacks(this);
}
public void onActivityResumed(Activity activity)
{
if(msg_updater != null)
{
msg_updater.set_app_is_active(true);
}
}
public void onActivityPaused(Activity activity)
{
if(msg_updater != null)
{
msg_updater.set_app_is_active(false);
}
}
public void onActivityStopped(Activity activity) {}
public void onActivityCreated(Activity activity, Bundle bundle) {}
public void onActivityStarted(Activity activity) {}
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {}
public void onActivityDestroyed(Activity activity) {}
}

Show full screen Incoming Call Activity in Android

In Android sometimes when we use an app and we receive a call , appears the full screen Incoming call activity
Instead if i create a new blank main activity and i put a simple BroadCast receiver, when im in the main activity and i receive a call this compares:
There is a way to show the full screen incoming call or just hide the incoming call popup notification ?
I searched a lot but i have not found anything...
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static class PhoneStateReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "OK", Toast.LENGTH_LONG).show();
}
}
}
in android The system UI may choose to display a heads-up notification, instead of launching your full-screen intent, while the user is using the device. check it out Display time-sensitive notifications

Send data from BroadcastReceiver to activity, while app is in background

I am writing my code in Android Studio, but the project that I am writing has no GUI, and never updates views for a user. It simply listens for the last installed app with a Broadcast Receiver and sends info to another java file.
I am wondering how I can send a string from a broadcast receiver to an activity (maybe this should not be an "activity" but a "service"?), and have this work while the app is in the background.
Right now I have a broadcast receiver listening for the last installed app on my phone (this runs in the background). And I have a custom broadcast receiver set up to notify my main activity when the broadcast receiver gets an installed app. But this custom receiver doesn't work in the background. Again, maybe I shouldn't be using an Activity to receive info from the BroadcastReceiver?
Is there a way I can send information from my broadcast receiver to my main activity while the app is in the background? I also need my main activity to resume normal function while in the background (there are no GUI updates done while it's in the background).
My BroadcastReceiver which is sending data to my Main Activity through a new Intent
public class NewInstallReceiver extends BroadcastReceiver {
ApplicationInfo ai;
#Override
public void onReceive(Context context, Intent intent) {
final PackageManager pm = context.getPackageManager();
try {
// if app is added, get package info
ai = pm.getApplicationInfo(intent.getData().getSchemeSpecificPart(), 0);
Intent i = new Intent("broadcastName");
// Data pass to activity
i.putExtra("appInfo", ai);
context.sendBroadcast(i);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
}
}
In my MainActivity in onCreate I register the receiver:
registerReceiver(broadcastReceiver, new IntentFilter("broadcastName"));
I receive data from BroadcastReceiver
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// get applicationInfo
Bundle b = intent.getExtras();
Object applicationInfo = b.get("appInfo");
ApplicationInfo appInfo = (ApplicationInfo) applicationInfo;
getNewData(appInfo);
}
};
Then I have to unregister the receiver in MainActivity, but obviously this doesn't allow for me to receive info from BroadcastReceiver once the app goes in the background
#Override
public void onStop()
{
try{
unregisterReceiver(broadcastReceiver);
}
catch(Exception e){
System.out.println("Exception is " + e.toString());
}
super.onStop();
}
Honestly, I don't think that update an Activity that is in background is a good practice (even if possible).
According to DOCS:
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View). While activities are often presented to the user as full-screen windows, they can also be used in other ways: as floating windows... or embedded inside of another activity (using ActivityGroup).
So, if the Activity is in background, it does not visible. So, it is useless to update its contents (because it is not visible to user).
In fact, you should implement following behavior instead:
Use your Service only to save the information (in a database/content provider) and to notifies the Activity that a new information is available. Then, if your activity is open, it immediately consumes that information. If Activity is not opened, the info remains saved for when the user needed it.
If app was only stopped, you can update the Activity content during onResume() method.
If your app was killed and user opened it again, you can update ALL Views during onCreate() method. onCreate() is called before the View is displayed to user.
This way, the info will be updated when needed: when the user wan's to check the info. Otherwise, it is a waste of time.

Android: how do I tell my activity to start new activity from my service?

I have a service that is, among other things, downloading images from internet. When this is done I want to show this image in a custom Activity that has a dialog theme. But I only want to use this pop up if the app is running, otherwise I just want to create a notification.
But I get an exception when I try to start an activity from my service and i feel that maybe this isn't the right way to do it?
It says:
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
So my question is if this is the right way to do this by setting that flag or how should I get my downloaded image from my service to an activity. Can I in some way tell an activity to start a new activity from my service class?
I think using Broadcast Receiver is better option for you.
Add Below Method in Service and call this method when image Download Complete.
private void updateMyActivity(Context context) {
if(MainActivity.activityStatusFlag){
//update the activity if activityStatusFlag=true;
Intent intent = new Intent("mUpdateActivity");
context.sendBroadcast(intent);
}else{
//display notification if activityStatusFlag=false;
}
}
In Activity Add Following Code.
public class MainActivity extends Activity{
public static boolean activityStatusFlag= false;
//define this variable to check if activity is running or not.
#Override
protected void onResume() {
super.onResume();
activityStatusFlag = true;
this.getApplicationContext().
registerReceiver(mMessageReceiver,new IntentFilter("mUpdateActivity"));
}
#Override
protected void onPause() {
super.onPause();
activityStatusFlag = false;
this.getApplicationContext().unregisterReceiver(mMessageReceiver);
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Display Popup or update Activity
}
};
}

Categories