10

I am working on an application, wherein after say 5 times the app is opened by a user, at 6th attempt the app should ask for feedback from user. I tried using Activity OnStart,OnResume, but its not working out since even after leaving and re-entering activity these methods are called. Also as per android functionality, I cannot quit app so that I can find it out from the first activity called. How do I find how many times the app was launched?

I hope this is not confusing.

Edit

Alternatively is there a way, wherein I can always resume my app from the first activity( or welcome page for eg.), once user presses home to quit the app.

Tushar Vengurlekar
  • 7,649
  • 8
  • 33
  • 48
  • store your visit count in shared preference and increment it every time the oncreate/onresume is called – Dinash Apr 27 '11 at 05:38
  • 3
    Thats the problem dinash, I cannot count by Onstart/onResume, that will not give me correct count, as those are also called while switching activities. – Tushar Vengurlekar Apr 27 '11 at 05:44
  • then increment count only in oncreate method of the application's main activity – Dinash Apr 27 '11 at 05:49
  • Again this cannot be done since, user may quit app at any point from any activity by pressing home. And since the app is not killed, when user reopens the app, he is taken to the activity that was opened last. – Tushar Vengurlekar Apr 27 '11 at 05:53
  • @Tushar Vengurlekar You CAN count the number of hard kills (user hits back button on main activity) by writing to prefs on a hard kill only. I can post code if this is what you want. – JAL Apr 27 '11 at 06:20
  • @JAL..I am not going for hard kills.so this solution will not work for me. – Tushar Vengurlekar Apr 28 '11 at 06:41

6 Answers6

17

This is actually quite simple. Using SharedPreference or the Database.

during OnCreate add 1 to the numberofTimes counter and commit.

OnCreate (Bundle bundle){
  mPref = getPreferences();
  int c = mPref.getInt("numRun",0);
  c++;
  mPref.edit().putInt("numRun",c).commit();
  //do other stuff...
}

OnCreate is called regardless of you start the app or you resume the app, but isFinishing() returns true if and only iff the user (or you) called finish() on the app (and it was not being destroyed by the manager)

This way you only increment when you are doing fresh start.

the isFinishing() Method inside of a OnPause method to check to see if the activity is being finish() or just being paused.

@Override
protected void OnPause(){
  if(!isFinishing()){
    c = mPref.getInt("numRun",0);
    c--;
    mPref.edit().putInt("numRun",c).commit();
  }
  //Other pause stuff.
}

This covers all your scenarios:

1. user starts app/activity (+1)-> finishes app, exit with finish()
2. user starts app (+1) -> pause (-1) -> returns (+1)-> finish
3. user starts app (+1) -> pause (-1) -> android kills process (0) -> user returns to app (+1) -> user finish.

every scenario you only increment the "times run" counter once per "run" of the activity

Dr.J
  • 1,220
  • 8
  • 9
  • 1
    I think you should place c++ inside onStart(or onResume), and c-- in onStop(or onPause). Take a look at activity life cycle: http://developer.android.com/reference/android/app/Activity.html – Helin Wang May 30 '13 at 16:51
  • Like @Helin Wang said, the life cycle is different –  Jun 18 '14 at 22:49
  • Besides, I believe the last scenario is not correct, because you are not counting the first launching. 1º "user starts app (+1) -> pause (-1) -> android kills process (0)" (result = 0), 2º "user returns to app (+1) -> user finish." (result = 1, like your first scenario). I have posted a possible solution for this. –  Jun 19 '14 at 00:22
  • This isnt really correct. When you go to a different activity from the main activity and return back, it will do c--. The onresume should do this c++. – Srujan Barai Aug 18 '16 at 07:13
4

Just:

  1. declare:

    private SharedPreferences prefs;
    private SharedPreferences.Editor editor;
    private int totalCount;
    
  2. initialize in onCreate():

    prefs = getPreferences(Context.MODE_PRIVATE);
    editor = prefs.edit();
    
  3. print or count wherever you want (any where in onCreate() or any specific click as you specified):

     totalCount = prefs.getInt("counter", 0);
     totalCount++;
     editor.putInt("counter", totalCount);
     editor.commit();
    
  4. now print totalCount where you want to count e.g.:

     System.out.println("Total Application counter Reach to :"+totalCount);
    
zdenek
  • 21,428
  • 1
  • 12
  • 33
Nirav Mehta
  • 1,715
  • 4
  • 23
  • 42
  • This answer is the best how-to `SharedPreferences` I've been able to found online although I had to edit the declarations and to completely substitute step 4 method for a `TextView` and then to import the variable to another activity. – JorgeAmVF Apr 18 '18 at 15:32
2

if you have a starting activity for app launch then you can implement it in following ways 1. Database:- through database you can save your application launch count and retrieve it on create of activity.

  1. Static Variable:- static variable also retain values during application start and end

  2. Application Preference:-you can store value in application preference and use it

problem with 2 and 3 approach is that if you switch off and on again your phone you will loose data. but if you still want to use 2 or 3 approach then 2 approach is very simple and

sample code for 3rd approach here

well you have to extends Application class and create a subclass from that

public class MyApp extends Application{
int visitCount;
onCreate(){
 visitCount=0;
}

and you can mention it in your menifest file like

<application name="MyApp">

.....
</application>

and in onCreate of your activity you can get it by

MyApp myApp=(MyApp)getApplicationContext();

Edit1: subclass your activity and override method

public class myActivity extends Activity{

   @Override
   onSaveInstanceState(Bundle outState){
      super.onSaveInstanceState(outState);
      counterFlag=true;
   }
}

it is get called when user press home button

and again override onResume() and check whether your counter flag is enabled or not and create all your activity by subclassing your MyActivity

also if any other activity has exit point on click of back button then you can override

   @Override
   public void back_pressed(){

   }

and do your task accordingly

Sunil Pandey
  • 7,042
  • 7
  • 35
  • 48
  • Thanks Sunil, Saving the count part is ok. But my main problem is how do I know the app is opened. I am using Application class in my app. But if user clicks Home key a[[ is paused and when user returns app resumes but OnCreate method from application class is not called. – Tushar Vengurlekar Apr 27 '11 at 06:01
  • well that will get called only once because android does not kill the application on home or back key press. you have to use any startup activity onCreate method to perform your function – Sunil Pandey Apr 27 '11 at 06:07
  • Sunil, I have mentioned in my last comment for the question. The stat-up activity will be called when new application instance starts. at home key press the the application is paused so the start-up activity will not be called. The app will resume from where it paused last time. – Tushar Vengurlekar Apr 27 '11 at 06:19
  • Thanks Sunil, I checked it, onSaveInstanceState is called on press of home button but it is also called when activity is killed, I tested it ad it is also in android docs. – Tushar Vengurlekar Apr 27 '11 at 07:03
  • i think if you manually manage a flag and use it in subclassed activity then you can achieve your goal – Sunil Pandey Apr 27 '11 at 11:30
1

I think this would be the best option in order to cover all scenarios:

private static boolean valueOfLaunchCountModified = false;

@Override
protected void onCreate(Bundle savedInstanceState) {

    if(!valueOfCountModified){
        preferences = getPreferences(MODE_PRIVATE);
        launchCount= preferences.getInt("launchCount", 0);
        if(preferences.edit().putInt("launchCount", ++launchCount).commit()){
            valueOfCountModified = true;
            if(launchCount == 5){
                //Do whatever you want
            }
        }
    }
}

If we remember the definition of a static variable ("...They are associated with the class, rather than with any object. Every instance of the class shares a class variable...") we will discover that is perfect for us.

When onPause method or an orientation change is executed the value of "valueOfLaunchCountModified" doesn't change; however, if the app process is destroyed, the value of "valueOfLaunchCountModified" changes to false.

0

I prefer to use onResume to track launch count since it’s getting called in every scenario (refer to Android Activity Lifecycle) when the activity is shown.

onResume could be called quite frequently depending on usage pattern, so instead of tracking launch count, it would be better to track launch session (as in only 1 launch count would be tracked per hour).

@Synchronized fun appSessionCount(sharedPref: SharedPreferences): Boolean {
    val now = LocalDateTime.now(ZoneOffset.UTC)

    val firstSeconds = sharedPref.getLong(KEY_FIRST_LAUNCH_DATE, 0)
    if (firstSeconds == 0L) {
        sharedPref.edit {
            putLong(KEY_FIRST_LAUNCH_DATE, now.atZone(ZoneOffset.UTC).toEpochSecond())
        }
    }

    val seconds = sharedPref.getLong(KEY_LAST_SESSION_DATE, 0)
    val lastDate = if (seconds > 0) LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneOffset.UTC) else null

    var count = sharedPref.getLong(KEY_SESSION_COUNT, 0)

    // first time or 1 hour ago
    if (lastDate == null || Duration.between(lastDate, now).toHours() >= 1) {
        sharedPref.edit {
            putLong(KEY_SESSION_COUNT, count + 1)
            putLong(KEY_LAST_SESSION_DATE, now.atZone(ZoneOffset.UTC).toEpochSecond())
        }
        return true
    }

    return false
}

I run the code at onResume of my main activity.

class MainActivity : AppCompatActivity() {
    lateinit var sharedPref: SharedPreferences

    override fun onCreate(savedInstanceState: Bundle?) {
        sharedPref = getSharedPreferences("LuaApp", Context.MODE_PRIVATE)
    }

    override fun onResume() {
        super.onResume()

        appSessionCount(sharedPref)
    }
}

https://code.luasoftware.com/tutorials/android/android-track-app-launch-count/

Desmond Lua
  • 6,142
  • 4
  • 37
  • 50
0

If you only want to count "true" invocations then extend Application and place counter logic into Application#onCreate. This could be a simple preference

Bostone
  • 36,858
  • 39
  • 167
  • 227