I have two activities, A(Login) and B(DashBoard), i create notification for specific times and if the user is already in activity B, then on clicking on the notification nothing should happen and if Application is closed or not opened, on clicking on notification Activity A needs to be opened. how can this be achieved.TIA
i tried the following in braodcastreceiver
#Override
public void onReceive(Context context, Intent intent) {
Log.e("NotificationReceiver","NotificationReceiver");
if(ActivityB.instance!=null){
}else{
Intent i = new Intent();
i.setClassName("com.test","com.test.ActivityA");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
But when my application not opened or closed, else is not executing.
Keep a track of activities in your application class using activityLifeCycleCallbacks
public class MyApplication extends Application implements my.package.ActivityLifecycleCallbacks{
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityStopped(Activity activity) {
Log.i("Tracking Activity Stopped", activity.getLocalClassName());
}
#Override
public void onActivityStarted(Activity activity) {
Log.i("Tracking Activity Started", activity.getLocalClassName());
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
}
#Override
public void onActivityResumed(Activity activity) {
Log.i("Tracking Activity Resumed", activity.getLocalClassName());
}
#Override
public void onActivityPaused(Activity activity) {
Log.i("Tracking Activity Paused", activity.getLocalClassName());
}
#Override
public void onActivityDestroyed(Activity activity) {
Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Tracking Activity Created", activity.getLocalClassName());
}
}
Next receive onClick of the notification in a broadcast, check if activityB is opened from your application class and make a decision
Related
I am creating one app In which I want to check status of activity like activity is in foreground or in background.this is working perfect from code but I want to bring activity to foreground when it is in background for that I am using service so when activity is going to background state I am calling that service and from that service I am launching activity but service is working ok upto version 10 after that same code of intent is not working.
This is my code.
MainActivity.Java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(android.os.Build.VERSION.SDK_INT>=29 &&
!Settings.canDrawOverlays(getApplicationContext())) {
MainActivity.this.startActivity(new
Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
}
}
This is DigitalApp class which extend application and from this I am calling service.
public class DigitalApp extends Application implements Application.ActivityLifecycleCallbacks
{
private int activityReferences = 0;
private boolean isActivityChangingConfigurations = false;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(Activity activity) {
if (++activityReferences == 1 && !isActivityChangingConfigurations) {
// App enters foreground
Toast.makeText(this,"App is in foreground with
activity::"+activity.getLocalClassName(),Toast.LENGTH_LONG).show();
Log.d("Tracking Activity Started", activity.getLocalClassName());
Log.d("TAG","App is in foreground");
}
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
Toast.makeText(this,"App enters background with
activity::"+activity.getLocalClassName(),Toast.LENGTH_LONG).show();
isActivityChangingConfigurations = activity.isChangingConfigurations();
if (--activityReferences == 0 && !isActivityChangingConfigurations) {
// App enters background
Log.d("Tracking Activity Stopped", activity.getLocalClassName());
Log.d("TAG","App enters background");
Intent i= null;
getApplicationContext().startService(new
Intent(getApplicationContext(),service.class));
}
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
This is Service class.
#Override
public void onCreate() {
super.onCreate();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "IN HANDLER OF SERVICE",
Toast.LENGTH_LONG).show();
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(i);
}, 3000);
}
I am passing intent in handler to launch activity when it is going to background state.handler is in oncreate method of service.I want launch activity from there again after it is going to background state.
I am using flag new task but with this flag activity is not launching will I add other flags?
from the onStop() of your activity start the service like this-
fun launchService(){
val serviceIntent = Intent(this, LaunchAppService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent)
}else{
startService(serviceIntent)
}
}
and show notification for foreground service like this
I have a situation, that when my app goes in background (not killed completely!) and last alive activity was BActivity. In this state. I receive a push notification.
When notification is clicked it should open the last activity which was opened earlier i.e., (BActivity).
Question How to open that last specific paused activity?
Is any answer like set flag or manifest configs?
If I understood correctly, you want to bring your app back to foreground after you receive a push notification? In that case, use the following code:
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(intent);
where MainActivity is the launcher Activity that you have specified in AndroidManifest.xml.
This should bring your app to foreground in its previous state, if there ever was one, and otherwise launch MainActivity.
For an explanation see here.
You can try by adding the activity life cycle callback to your application. And judge the activity type of current paused or resumed activity, etc. The sample code:
public static void init(Application app) {
app.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
private int activityCount = 0;
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
AppUtils.attachActivity(activity);
}
#Override
public void onActivityStarted(Activity activity) {
activityCount++;
AppUtils.attachForeActivity(activity);
}
#Override
public void onActivityResumed(Activity activity) {
if (!isForeGround) {
isForeGround = true;
notifyForegroundChange(true);
}
}
#Override
public void onActivityPaused(Activity activity) {
// no-op
}
#Override
public void onActivityStopped(Activity activity) {
AppUtils.detachForeActivity(activity);
activityCount--;
if (activityCount == 0) {
isForeGround = false;
notifyForegroundChange(false);
Log.i(TAG, "Activity foreground: " + System.currentTimeMillis());
}
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
// no-op
}
#Override
public void onActivityDestroyed(Activity activity) {
AppUtils.detachActivity(activity);
}
});
}
Here we use the activityCount filed to calculate current actived activities count. When it's 0, the app is background, otherwise foreground. You can judge the activity type by the callback method provided.
Hope it helps!
Hey I have an application where I want to now when the APP goes to onPause or onDestroy because I want to call a certain function when this happens.
I tried to override the onPause in an activity and extended that activity in all project but the onPause was being called on every migration between activities (which is logical) but this is not what I want.
I want to know when the user exits the app or pauses it (pressing the home button)
Regards,
Pull this dependency in your build.gradle file:
dependencies {
implementation "android.arch.lifecycle:extensions:1.1.1"
}
Then in your Application class, use this:
public class MyApplication extends Application implements LifecycleObserver {
#Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
private void onAppBackgrounded() {
Log.d("MyApp", "App in background");
}
#OnLifecycleEvent(Lifecycle.Event.ON_START)
private void onAppForegrounded() {
Log.d("MyApp", "App in foreground");
}
}
Update your AndroidManifest.xml file:
<application
android:name=".MyApplication"
....>
</application>
in all of your activities :
#Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
Log.e("TAG", "Activity Minimized");
}
in your main activity :
#Override
public void onBackPressed() {
Log.e("TAG", "App Exit");
super.onBackPressed();
}
note : there is no way to detect when app killed by system ( for example quit with task manager )
I use this method to detect if the app goes to background or is killed
step 1:
Make a service like this
public class OnClearFromRecentService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ClearFromRecentService", "Service Started");
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("ClearFromRecentService", "Service Destroyed");
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.e("ClearFromRecentService", "END");
//Code here
stopSelf();
}
}
step 2)register this service in manifest.xml
<service android:name="com.example.OnClearFromRecentService" android:stopWithTask="false" />
step 3) Then start this service on your splash activity
startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
So now when your app is manually killed, the onDestroy method will be called
Try this on your code and let me know if its working.
Happy Coding :)
If the user exits the application the onDestroy() callback will be called, if the user presses the home button the onStop() callback will be called.
So you want to know when the whole Application goes into Bacground, the method from Activity.onPause tells you when a single abtivity goes into background.
For your needs you could add
to your android manifest. this will call a class like this with name "YourApplication"
public class YourApplication extends Application {
#Override
public void onCreate() {}
public public void onTerminate() {
super.onTerminate();
}
}
e.g. for "onCreate" or "onTerminate" of the whole App (not for every single Activity).
But java documentation say you should not trust that onTerminate is called on every app destroy (see: android.app.Application subclass, onTerminate is not being called).
I Think the best way is, if you
add a own Methode "onPause" and "onResume" to your Application class
in ALL your Activities you store into Application class when onPause or onResume is called
and you call you own Application.onPause when ALL of you activities are in "onPause"
and you call you Application.onResume when first Activity is back in
"onResume"
Implement
Application.ActivityLifecycleCallbacks
in your Application Class. It will implement the following ActivityLifeCycle Methods :
isActivityVisible()
onActivityCreated()
onActivityStarted()
onActivityResumed()
onActivityPaused()
onActivityStopped()
onActivitySaveInstanceState()
onActivityDestroyed()
And Register the callback listener in OnCreate() of application class like :
registerActivityLifecycleCallbacks(this);
Define a Global variable in application class.
private static boolean isActive;
Now change the activity life cycle's overridden method like this:
public static boolean isActivityVisible() {
return isActive;
}
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
isActive = true;
}
#Override
public void onActivityPaused(Activity activity) {
isActive = false;
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
isActive = false;
}
and you can perform the required operations on the value of isActive variable.
I have an application where I'm using GCM and I want to receive notifications only when app is closed, but when it's foreground don't receive them.
So is there some functionality to disable GcmListenerService for a while?
You do this wrong way. It is irrelevant really when your app will receive GCM message. In your case it's more important when it react to it. So instead of disabling your application component, I'd simply put some logic that would either ignore messages under certain conditions (like it's in foreground) or handle them differently in that case. That, for me, looks like better way than turning your app completely deaf.
You will have to track if your app is in foreground / background using Activity Life cycle callback.
public class SampleApplication extends Application
{
private static int sRunningActivityCount = 0;
#Override
public void onCreate()
{
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks(){
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState)
{
}
#Override
public void onActivityStarted(Activity activity)
{
sRunningActivityCount++;
}
#Override
public void onActivityResumed(Activity activity)
{
}
#Override
public void onActivityPaused(Activity activity)
{
}
#Override
public void onActivityStopped(Activity activity)
{
sRunningActivityCount--;
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState)
{
}
#Override
public void onActivityDestroyed(Activity activity)
{
}
});
}
public static boolean isAppBackground()
{
return sRunningActivityCount == 0;
}
public static boolean isAppForeground()
{
return sRunningActivityCount != 0;
}
}
You can use the following to enable/disable receiving GCM notifications:
public void setNotifications(boolean enabled)
{
mPackageManager.setComponentEnabledSetting(new ComponentName(mContext, YourGcmListenerService.class), enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Intent intent = new Intent(mContext, YourGcmListenerService.class);
if (enabled)
{
mContext.startService(intent);
}
else
{
mContext.stopService(intent);
}
}
I have a single Activity and one Service. The activity is used for search and the service is used to display a hovering widget over all the screens like Facebook chat head does.
When the user leaves the activity like pressing back key I start a service and the widget starts hovering. On Clicking the hovering widget the activity is again relaunched from service by using FLAG_ACTIVITY_NEW_TASK. But doing this when my activity is overlapped by other app activity neither onStop() nor onPause() is getting called. onStop() is called when the activity on top of it onStop() is called.
Can someone explain why this is happening? Thanks in advance.
Activity Code:
public class CouponSearchActivity extends AppCompatActivity {
public static final String TAG = CouponSearchActivity.class.getSimpleName();
public static final String BROADCAST_ACTION_ACTIVITY_STARTED =
"activity_created";
public static final String BROADCAST_ACTION_ACTIVITY_STOPPED = "activity_stopped";
public static void startActivity(Context context){
Intent intent = new Intent(context, CouponSearchActivity.class);
context.startActivity(intent);
}
public static void startActivityFromService(Context context){
Intent intent = new Intent(context, CouponSearchActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TAG",": onCreate()");
setContentView(R.layout.activity_coupon_search);
CouponWidgetService.stopService(this);
if(savedInstanceState == null){
initCouponSearchFragment();
}
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d("TAG",": onNewIntent()");
}
private void initCouponSearchFragment(){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.container, CouponSearchFragment.newInstance()).commit();
}
private void sendBroadcast(){
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION_ACTIVITY_STARTED);
sendBroadcast(intent);
Log.d("Broadcast sent", action = " +BROADCAST_ACTION_ACTIVITY_STARTED);
}
#Override
protected void onResume() {
super.onResume();
Log.d("TAG","onResume()");
sendBroadcast();
CouponWidgetService.stopService(this);
}
#Override
protected void onPause() {
super.onPause();
Log.d("TAG + "onPause()");
}
#Override
protected void onStop() {
super.onStop();
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION_ACTIVITY_STOPPED);
sendBroadcast(intent);
Log.d("TAG", "onStop()");
Log.d("Broadcast sent", action = " + BROADCAST_ACTION_ACTIVITY_STOPPED);
CouponWidgetService.startService(this, StoreCoupons.getStoreCouponsResponse(), StoreCoupons.getSelectedCategories());
}
#Override
public void onBackPressed() {
Log.d("onBackPressed()");
//CouponWidgetService.startService(this, StoreCoupons.getStoreCouponsResponse(), StoreCoupons.getSelectedCategories());
super.onBackPressed();
}
But doing this when my activity is overlapped by other app activity
neither onStop() nor onPause() is getting called.
This looks like a legit behavior to me. When your Activity is overlapped by some other Activity, onPause will be called. If the "overlap" is complete (i.e. your Activity is no longer visible), then its onStop should also be called.
At some later time, when you click on "hovering widget", your Activity is already paused (and, potentially, stopped), therefore it won't get those lifecycle callbacks again.