Detecting state of application resume from different navigation state android - android

I want to record state of application when it is resumed/created from different point of entry.
app is opened from app drawer
app is opened from notification
app is opened from open apps (Long home press)
app is resumed from other screen
I know it can be traced by generating a base activity and overriding resume/pause events, but I have bulk of activity present in app. so is there any short method to get the state of application?
I thought about creating a service and continuously checking current running tasks, but I can only use this approach if I found a way to run the service only when my activity is in visible state. (for that to bind service in each activity is not practical for me)

Your suggested solution sounds good to me:
public class YourBaseActivity extends Activity {
#Override
protected void onResume() {
super.onResume();
ActivityManager mgr = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = mgr.getRunningTasks(1);
tasks.get(0).topActivity.getClassName();
//Do what you need to do with it...
}
}
And let all your activities extends this one instead of Activity should work for you
EDIT
Another way to do it:
Create your own application class and implement Application.ActivityLifecycleCallbacks, a working example of the code:
public class ApplicationTest extends Application implements Application.ActivityLifecycleCallbacks {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
Log.d("testing", "onActivityResumed");
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
}
And reference this class in your manifest:
<application
...
android:name="com.example.testing.ApplicationTest" >

Related

Android, How do I know if the application has closed

I need to know when the user close the App, not when the user press on the "home" button, but when the user close the App at the "recent applications menu".
At those two cases the App go to the onPause method. Is there any way to tell them apart?
I`m asking because, I want to delete the user from my database on one situation, and not at the other.
you can try combining multiple callbacks from the activity lifecycle.
onUserLeaveHint() can be realy usefull to get know if the activity is in background or foreground
isFinishing(): can bu used to know if the activity is been closed by a finish() call or if is the system shutting down the activity to free resources
you can try using a Service for that, in this service override onTrimMemory method
#Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
//app was closed
break;
}
}
check more about services
I'm not sure, but maybe ActivityLifecycleCallbacks can help you. It need to test.
Example:
public class YourApplication extends Application {
#Override
public void onCreate() {
lifecycleListener = new ActivityLifecycleListener();
registerActivityLifecycleCallbacks(lifecycleListener);
}
public class ActivityLifecycleListener implements Application.ActivityLifecycleCallbacks {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
}

Application Level onResume Android

Problem
The idea is very simple. Whenever an user comes back to my app from the Recents I want to show a simple dialog prompting with the password.
I know how to prompt the dialog with password, but my problem is how do I understand that the user has entered my app from the recents. If I put the prompt in the onResume in every activity, then it will get triggered everytime even if the user doesn't enter from the Recents menu.
There are lots of activities and fragments in my app. So, I would love to have a more generic or application level solution.
Implement Application.ActivityLifecycleCallbacks, that will provide all activity callback in your application class.
public class AppController extends Application implements
Application.ActivityLifecycleCallbacks
{
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
You could try with this flag FLAG_ACTIVITY_LAUNCHER_FROM _HISTORY:
if((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY )!=0){
Log.d(TAG, "Called from history");
//clear flag from history
Intent intent = getIntent().setFlags( getIntent().getFlags() & (~ Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY));
setIntent(intent);
}
Source : Android - detecting application launch from home or history
When "A" Activity is start from recent, this flag is present.
Now this flag will be also present if "A" activity call "B" activity and on "B" user press back.
So you have to check flag and when you detect it you have clear intent by removing this flag, source: Remove a Paint Flag in Android
Try below sample
/**
* TODO : After update to API level 14 (Android 4.0),
* We should implement Application.ActivityLifecycleCallbacks
*/
public class GlobalApplication extends android.app.Application
{
private boolean inForeground = true;
private int resumed = 0;
private int paused = 0;
public void onActivityResumed( Activity activity )
{
++resumed;
if( !inForeground )
{
// Don't check for foreground or background right away
// finishing an activity and starting a new one will trigger to many
// foreground <---> background switches
//
// In half a second call foregroundOrBackground
}
}
public void onActivityPaused( Activity activity )
{
++paused;
if( inForeground )
{
// Don't check for foreground or background right away
// finishing an activity and starting a new one will trigger to many
// foreground <---> background switches
//
// In half a second call foregroundOrBackground
}
}
public void foregroundOrBackground()
{
if( paused >= resumed && inForeground )
{
inForeground = false;
}
else if( resumed > paused && !inForeground )
{
inForeground = true;
}
}
}
Put below code in your all activities.
public class BaseActivity extends android.app.Activity
{
private GlobalApplication globalApplication;
#Override
protected void onCreate()
{
globalApplication = (GlobalApplication) getApplication();
}
#Override
protected void onResume()
{
super.onResume();
globalApplication.onActivityResumed(this);
}
#Override
protected void onPause()
{
super.onPause();
globalApplication.onActivityPaused(this);
}
#Override
public void onDestroy()
{
super.onDestroy();
}
}
I would suggest using LifecycleObserver. If your Application class implements this interface it marks a class as a LifecycleObserver, it does not have any methods, instead, it relies on OnLifecycleEvent annotated methods. The usage is simple:
public class AndroidApplication extends Application implements LifecycleObserver {
#OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onAppStart() {
//enter code here
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppStop() {
//enter code here
}
...etc
}
With Lifecycle.Event you can access all lifecycle states through Enum. It is part of androidx.

How does automatic activity tracking work for google analytics android

I've implemented something similar for iOS using a quick swizzle of viewDidAppear to allow my company to track flow around the app in our own internal systems.
Now, ideally I'd like to avoid having to implement appear & disappear tracking in every activity for our internal use, so was hoping someone could shed some light into how the GA library achieves this.
I had a good google around and couldn't find any kind of internal event that's posted when an activity comes into the foreground so am at a bit of a loss at the moment.
Cheers!
I know the following is not a direct answer to your question but why not applying a basic OOP principle? Inheritance.
import android.app.Activity;
public class BaseActivity extends Activity {
#Override
protected void onResume() {
super.onResume();
// hit when activity appears. Tell Appserver!
}
#Override
protected void onPause() {
super.onPause();
// hit when activity hides. Tell Appserver!
}
}
and then have your other Acivities extend this instead of android.app.Activity?
You can use ActivityLifecycleCallback. Example below:
public class MordorApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleLogger());
}
}
public class ActivityLifecycleLogger implements Application.ActivityLifecycleCallbacks {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
createActivityStateLog(activity, "created");
}
#Override
public void onActivityStarted(Activity activity) {
createActivityStateLog(activity, "started");
}
#Override
public void onActivityResumed(Activity activity) {
createActivityStateLog(activity, "resumed");
}
#Override
public void onActivityPaused(Activity activity) {
createActivityStateLog(activity, "paused");
}
#Override
public void onActivityStopped(Activity activity) {
createActivityStateLog(activity, "stopped");
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
createActivityStateLog(activity, "savingStateInstance");
}
#Override
public void onActivityDestroyed(Activity activity) {
createActivityStateLog(activity, "destroyed");
}
private void createActivityStateLog(Activity activity, String state) {
String log = String.format("Activity %s - %s", activity.getClass().getName(), state);
LOG.debug(log);
}
private static final Logger LOG = LoggerFactory.getLogger(ActivityLifecycleLogger.class);
}
Google Analytics has automatic Activity tracking feature.
See
https://developers.google.com/analytics/devguides/collection/android/v4/?hl=en#analytics-xml
or do John's answer :)
You can create delegate class (suppose GaUtils) then call that on resume/pause. Just one line, don't you?
#Override
protected void onPause() {
super.onPause();
GaUtils.onPause(screenName); // track pause
}

Is there a way to completely block the ability to take screenshots in Android?

I'm currently developing a light-weight application where in one part of the app I would like to COMPLETELY take away the ability to take a screenshot in Android. When I say screenshot, I'm talking about iPhone's "screen capture" feature. This is for security reasons. I realize there are apps out there that allow users in Android to do this as well, and I want to block this functionality. Any way of doing this is fine, whether disabling the hardware buttons, freezing the phone, or via software.
You can use the window LayoutParam FLAG_SECURE. Add this to your onCreate method:
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
More on this topic can be found here.
Add an application class in your project like that to prevent the full app from screen-shot (All Activity and Fragment around your app). This is the example project and below I mentioned the core code -
public class MyApplicationContext extends Application {
private Context context;
public void onCreate() {
super.onCreate();
context = getApplicationContext();
setupActivityListener();
}
private void setupActivityListener() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); }
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
});
}
}

How to trigger a method during app launch? (Android)

I'm trying to call a method when a user launch my application (no matter it is a fresh launch, or a return to it after hiding by home buttton)
For iOS, we can put the method in "applicationDidBecomeActive" in AppDelegate.m, so the method will be called when app launches.
However, for Android, if we put the method in onResume() in the 1st activity, not only app launch will call the method, backing to the the 1st activity from other activities in the same app will also call the method. I don't want this happen, I just want the method to be called when app launches.
I've asked it in the past but seems no answer on Android.
Any solutions? Thanks a lot.
You can implement your own Application class. MyApplication extends Application and set it as your Application in the manifest file AndroidManifest.xml.
<application
android:name="MyApplication"
.
.
. >
</application>
In MyApplication Class, implement onCreate() and onTerminate() methods.
onCreate() method called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.
See the docs for Application.
There is no method that is called only when the app returns from background, but you could implement something that you could implement something like this to see if the app started from background or it was first started. Create a general activity that will be extended by all the other activities and override onStart():
public abstract class CustomActivity extends FragmentActivity {
public static int ACTIVITIES_RUNNING = 0;
#Override
protected void onStart() {
super.onStart();
if (ACTIVITIES_RUNNING == 0) {
//app came from background
//start whatever you want
}
Const.ACTIVITIES_RUNNING++;
}
}
First create singleton for counting activities in foreground
public class ActivitiesCounter {
public interface ApplicationLaunchListener{
public void onLaunch();
}
private int mCounter = 0;
private ApplicationLaunchListener mListener;
private static ActivitiesCounter mInstance = new ActivitiesCounter();
public static ActivitiesCounter getInstance(){
return mInstance;
}
public void increase(){
if(mCounter == 0){
if(mListener != null){
mListener.onLaunch();
}
}
mCounter++;
}
public void decrease(){
mCounter--;
}
public void setApplicationLaunchListener(ApplicationLaunchListener listener){
mListener = listener;
}
}
Then activity:
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ActivitiesCounter.getInstance().setApplicationLaunchListener(new ActivitiesCounter.ApplicationLaunchListener() {
#Override
public void onLaunch() {
Toast.makeText(MyActivity.this, "launched", Toast.LENGTH_LONG).show();
}
});
findViewById(R.id.btn_activity_b).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity.this, ActivityB.class);
startActivity(intent);
}
});
}
#Override
protected void onStart() {
super.onStart();
ActivitiesCounter.getInstance().increase();
}
#Override
protected void onStop() {
ActivitiesCounter.getInstance().decrease();
super.onStop();
}
}
Activity B also should increase and decrease counter
public class ActivityB extends Activity {
#Override
protected void onStart() {
super.onStart();
ActivitiesCounter.getInstance().increase();
}
#Override
protected void onStop() {
ActivitiesCounter.getInstance().decrease();
super.onStop();
}
}
It's better create BaseActivity (with onStart, onStop) for all activities in your app (then, you don't need override onStart, onStop every time)
You can define a superclass for all your activities and track the state of the app. If all activities are in stopped state - app in the background, otherwise - in the foreground. In onStart() and onStop() methods of your super activity you can increment and decrement the number of visible activites. Then in onStart() check if there was any currently visible activites. If no - app becomes active and you can call your method:
public class SuperActivity extends Activity {
private static int mVisibleActivitiesCount;
#Override
public void onStart(){
super.onStart();
if (mVisibleActivitiesCount == 0) {
onAppBecomesActive();
}
mVisibleActivitiesCount++;
}
#Override
public void onStop(){
super.onStart();
mVisibleActivitiesCount--;
}
private void onAppBecomesActive() {
// Do some staff
}
}
Open the androidManifest.xml from the Manifests Folder
Choose the Activity you want to open when app start
Add these codes to that Activity
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Remember to removes this code from the activity in which its already present(usually MainActivity)

Categories

Resources