How does automatic activity tracking work for google analytics android - 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
}

Related

How to detect if activity stack is empty and activity stack size?

One method is to pass a bundle/store in sharedpreference through which this information is obtained. Is there a method other than such to achieve this? In fragments you can do a getBackStackEntryCount.
In your Application class, register a listener for Activity life cycle events:
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// add to stack
}
#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) {
// remomve from stack
}
});
}
}
Then you just need to keep track of your activities in a list (do not put the Activity itself, put the name or a weak reference to it). You can monitor other events as needed.

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.

Detecting state of application resume from different navigation state 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" >

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) {
}
});
}
}

Categories

Resources