0

My goal is to detect when the user goes into the background. I used this answer to get me setup

However when I replace where there is "MyApplication" in his code, with my classname ("MainActivity"). I can the inconvertible types error.

I'm new to android studio and do not know how to go about fixing this. Any and help is appreciated.

Main Activity Code:

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {



    private Timer mActivityTransitionTimer;
    private TimerTask mActivityTransitionTimerTask;
    public boolean wasInBackground;
    private final long MAX_ACTIVITY_TRANSITION_TIME_MS = 2000;

    @Override
    public void onResume()
    {
        super.onResume();

        MainActivity myApp = (MainActivity)this.getApplication();
        if (myApp.wasInBackground)
        {
            //Do specific came-here-from-background code
        }

        myApp.stopActivityTransitionTimer();
    }

    @Override
    public void onPause()
    {
        super.onPause();
        ((MainActivity)this.getApplication()).startActivityTransitionTimer();
    }

   public void startActivityTransitionTimer() {
        this.mActivityTransitionTimer = new Timer();
        this.mActivityTransitionTimerTask = new TimerTask() {
            public void run() {
                MainActivity.this.wasInBackground = true;
            }
        };

        this.mActivityTransitionTimer.schedule(mActivityTransitionTimerTask,
                MAX_ACTIVITY_TRANSITION_TIME_MS);
    }

    public void stopActivityTransitionTimer() {
        if (this.mActivityTransitionTimerTask != null) {
            this.mActivityTransitionTimerTask.cancel();
        }

        if (this.mActivityTransitionTimer != null) {
            this.mActivityTransitionTimer.cancel();
        }

        this.wasInBackground = false;
    }

}

Location of error

EDIT: AndroidManifest.xml below:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jstudios.cars">


    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Cars"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".SplashActivity"
            android:label="@string/app_name"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden"
            android:label="CarsApp"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme.NoActionBar"></activity>
    </application>

</manifest>

Intent filter is for the splash screen.

EDIT: @Modi Harsh

LifeCycleObserverClassCode:

enter image description here

Directories Of LifeCycleObserver:

enter image description here

Input of Code in MainActivity:

enter image description here

EDIT 2 ERROR IN MainActivityJava:

enter image description here

EDIT 2 ERROR IN MyLifeCycleObserverClass:

enter image description here

JavaHava
  • 189
  • 2
  • 15
  • 1
    Just carefully study the link you posted. You have to implement your instance of application (don't forget to mention it in manifest). Your activity is not the same as your application, those two cannot be cast. – ror Jul 04 '19 at 16:35
  • Yeah I saw some of the comments referencing what your saying. I don't understand what you mean by implementing my instance of application. – JavaHava Jul 04 '19 at 16:41
  • https://stackoverflow.com/a/48767617/115145 – CommonsWare Jul 04 '19 at 16:48

2 Answers2

2

You need to create a class which extends Application - this is not the same as your Main activity. The docs describe it as:

Base class for maintaining global application state. You can provide your own implementation by creating a subclass and specifying the fully-qualified name of this subclass as the "android:name" attribute in your AndroidManifest.xml's tag. The Application class, or your subclass of the Application class, is instantiated before any other class when the process for your application/package is created.

It will look like this:

public class MyApplication extends Application {

}

Inside your Manifest.xml file you will need something like this to tell Android about your custom application class:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      package="your.package.name">

....

    <application
           android:name=".MyApplication"
           android:icon="@mipmap/ic_launcher"
           android:label="@string/app_name"
           android:roundIcon="@mipmap/ic_launcher_round"
           android:supportsRtl="true">
</manifest>

I think you need to move your startActivityTransitionTimer and stopActivityTransitionTimer methods to your new MyApplication class.

Then your onPause and onResume methods should be able to use this:

(MyApplication) this.getApplication()

PS you can call your MyApplication class anything you want.

PPS it might be worth reading about the fundamentals of Android components here

James Allen
  • 6,406
  • 8
  • 50
  • 83
  • Thanks for the clarification will definitely be reading those sources. I've followed your post instruction to the tee, but I still have same error. I think it's stemming from my application tab in the manifest. The error states "MyApplication is not assignable to android.app.application. I'm going to post my manifest files above maybe I'm overlooking something – JavaHava Jul 04 '19 at 17:36
1

It can be achieved through Android Architecture Component: LifeCycle

Add in build.gradle

implementation 'android.arch.lifecycle:extensions:1.1.1'

Create your Observer class and implements with LifecycleObserver

Kotlin :

class MyLifeCycleObserver : LifecycleObserver {

private var lifeCycleObserverCallback: LifeCycleObserverCallback? = null

    fun registerCallback(lifeCycleObserverCallback: LifeCycleObserverCallback) {
        this.lifeCycleObserverCallback = lifeCycleObserverCallback
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    private fun onAppForeground() {
        lifeCycleObserverCallback?.onForeground()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    private fun onAppBackground() {
        lifeCycleObserverCallback?.onBackground()
    }

    public interface LifeCycleObserverCallback {
        fun onForeground()
        fun onBackground()
    }
}

Java :

public class MyLifeCycleObserver implements LifecycleObserver {

    private LifeCycleObserverCallback lifeCycleObserverCallback;

    public void registerCallback(LifeCycleObserverCallback lifeCycleObserverCallback) {
        this.lifeCycleObserverCallback = lifeCycleObserverCallback;
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    private void onAppForeground() {
        lifeCycleObserverCallback.onForeground();
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    private void onAppBackground() {
        lifeCycleObserverCallback.onBackground();
    }

    public interface LifeCycleObserverCallback{
        void onForeground();
        void onBackground();
    }
}

Add this few lines in your Activity in onCreate

Kotlin :

val observer = MyLifeCycleObserver()
lifecycle.addObserver(observer)
observer.registerCallback(this)

Java :

MyLifeCycleObserver observer = new MyLifeCycleObserver();
getLifecycle().addObserver(observer);
observer.registerCallback(this);

After that implements LifeCycleObserverCallback listener in your Activity and override both methods

Kotlin :

override fun onForeground() {
//    do whatever you want (App in Foreground)
}

override fun onBackground() {
//    do whatever you want (App in Background)
}

Java :

@Override
public void onForeground() {
//    do whatever you want (App in Foreground)
}

@Override
public void onBackground() {
//    do whatever you want (App in Background)
}

And done :)

Modi Harsh
  • 555
  • 4
  • 7
  • Thanks for the help I'm implementing your solution. When you say create your observer class Observer class and extends with LifecycleObserver, do I put that section of code in my mainactivity.java? – JavaHava Jul 04 '19 at 22:34
  • No, not in your activity. create a separate `Observer` class file in your app package. – Modi Harsh Jul 05 '19 at 19:39
  • ok so the only sections of code that I put in the main activity are the val observer = MyLifeCycleObserver() section as well as the override fun onForeground section in your answer? – JavaHava Jul 05 '19 at 19:44
  • Yes, exactly (y) and don't forget to implement those `LifeCycleObserverCallback` methods inside your activity. If it is helpful to you please upvote the answer :) – Modi Harsh Jul 05 '19 at 19:46
  • Ok thanks! looking forward to this, when I get on android studio, I'll let you know how it goes. – JavaHava Jul 05 '19 at 19:48
  • Ok so I got some errors above I'm going to post where exactly I inputted your code – JavaHava Jul 06 '19 at 21:05
  • Code is written in `Kotlin` language so, you've to convert that code into `Java` or convert your code into `Kotlin`. – Modi Harsh Jul 07 '19 at 13:07
  • Ok so I re-added the java code. My mainactivtiy says cannot resolve lifecycle I'm posting images above. I think it has to do with my dependencies I'm using androidx – JavaHava Jul 07 '19 at 19:31
  • You can find all `AndroidX` libraries : https://developer.android.com/jetpack/androidx/migrate – Modi Harsh Jul 08 '19 at 17:15