34

Is it possible to programmatically read the date when my Android apk was built? I could not find anything in the PackageInfo class.

I want to expire beta versions of my app and the easiest way would be to read out such a date and expire it after a fixed period of days, so I don't have to update the code for that every time I build and deploy a beta version.

Ahmad Adibzad
  • 501
  • 2
  • 6
  • 14
infero
  • 843
  • 2
  • 11
  • 22
  • If you're trying to find when an app was first installed, you can use: `return activity.getPackageManager().getPackageInfo( activity.getPackageName(), 0 ).lastUpdateTime;`. – Joshua Pinter Nov 03 '18 at 01:42
  • @Joshua Pinter That still depends on the device's time/clock though. In my case, I'd like to detect whether the device's time is behind. Some phones will have their time reset if they have not been charged for days. My app requires the time to be up to date. Cut off time is 4 days behind. – TheRealChx101 Jan 17 '19 at 20:44

1 Answers1

68

12/2/22 Note: This is a newer way to put the timestamp into the BuildConfig.java than I suggested previously, but I am keeping the legacy instructions at the bottom for anyone who might want it. The instructions are for the relatively new build.gradle.kts format.

First, update build.gradle to include:

android {
    buildFeatures {
        buildConfig = true
    }
}

The above is needed as the buildConfigField feature may have been disabled by default, starting with Android Studio Flamingo Canary 9. See here for more about that.

Next, add to the top of build.gradle.kts:

 import com.android.build.api.variant.BuildConfigField

and outside of the android { ... } part of build.config.kts add this:

androidComponents {
    onVariants {
       it.buildConfigFields.put(
            "BUILD_TIME", BuildConfigField(
                "String", "\"" + System.currentTimeMillis().toString() + "\"", "build timestamp"
            )
        )
    }
}

As with the previous instructions, the build timestamp is accessed in Kotlin like this:

private val buildDate = Date(BuildConfig.BUILD_TIME.toLong())
Log.i("MyProgram", "This .apk was built on ${buildDate.toString()}");

That's it. Keep reading if you've got an older versions of Android Studio/Gradle and want the older more Java-oriented instructions.

Note 6/1/2020: Android Studio 4.1 Canary 10 w/Gradle >= 6.5 has updated instructions. If you are seeing an "Unsupported BuildConfig type : java.util.Date error, scroll down for the fix.

[Older Instructions]

In build.gradle, each of your build types should have a buildConfigField. (This is a simplified version of the configuration- you're likely to have other stuff in here, but I wanted to show where you put it):

android {
    signingConfigs {
        buildTypes {
            debug {
                buildConfigField "java.util.Date", "BUILD_TIME", "new java.util.Date(" + System.currentTimeMillis() + "L)"
            }
            release { 
                buildConfigField "java.util.Date", "BUILD_TIME", "new java.util.Date(" + System.currentTimeMillis() + "L)"
            }
        }
    }
}    

(Note that "BuildConfigField" is the newer version of "BuildConfigLine" as of the 0.8.0 build system.)

The next time gradle does assembleRelease or assembleDebug, it should generate:

./build/source/buildConfig/releaseORdebug/com/your/project/BuildConfig.java

Next, inside that BuildConfig file, you should see something has been auto-generated like:

public final class BuildConfig {
    public static final java.util.Date BUILD_TIME = new java.util.Date(1395794838381L);
}

So, to access the build date within your app....

Date buildDate = BuildConfig.BUILD_TIME;
Log.i("MyProgram", "This .apk was built on " + buildDate.toString());

(You can format the date however you like using a SimpleDateFormat.)

Update 6/1/2020 -- In Android Studio 4.1 Canary 10 w/Gradle 6.5, the above solution results in an "Unsupported BuildConfig type : java.util.Date" error. A slight variation to the above should be used instead:

android {
    signingConfigs {
        buildTypes {
            debug {
                buildConfigField("String", "BUILD_TIME", System.currentTimeMillis().toString())
            }
            release { 
                buildConfigField("String", "BUILD_TIME", System.currentTimeMillis().toString())
            }
        }
    }
} 

Update 7/30/2020 After gradle 6.6-rc4, you need to include the enclosing quotes for the time by changing to this line:

        buildConfigField("String", "BUILD_TIME", "\"" + System.currentTimeMillis().toString() + "\"")

Inside the BuildConfig file, you should see something has now been auto-generated like:

public final class BuildConfig {
      public static final String BUILD_TIME = "1590735284503";
}

So now, to access the build date within your app....

private Date buildDate = new Date(Long.parseLong(BuildConfig.BUILD_TIME));
Log.i("MyProgram", "This .apk was built on " + buildDate.toString());

As before, you can format the date however you like using a SimpleDateFormat.

Hope this is helpful.

fattire
  • 6,823
  • 3
  • 25
  • 38
  • you can use System.currentTimeMillis() instead of the function... – Marco Schmitz Oct 05 '16 at 10:33
  • Hmm. Tried that and didn't work (error: cannot find symbol variable buildTime) though compressing the function to ` Calendar.getInstance().getTimeInMillis();` does work for me. – fattire Oct 06 '16 at 08:07
  • I take it back. I just tried it again and it seems to work... making build.gradle a wee bit smaller. I'll update the answer.. Thanks, Marco! – fattire Nov 13 '16 at 04:58
  • I simply use this: buildConfigField "String", "buildTime", "new java.util.Date().toString()" . Any side effects I am not aware of? – qwlice Sep 20 '17 at 13:53
  • 2
    Thanks. it works very well. – Yamur Feb 07 '18 at 12:12
  • Hint: build your project after you edited gradle file, but before using BuildConfig.BUILD_TIME in code, else you may see "cannot find buildTime"! – allofmex Mar 20 '20 at 14:07
  • Not critical, but is there a way to get rid of the ''BUILD_TIME' value is being replaced...' warning in Build Output? – allofmex Mar 20 '20 at 15:44
  • As of Jul 2021, the original solution using java.util.Date works for me with Android Studio Arctic Fox Beta 5 on MacOS 11.4 ARM (Gradle 7.0.2, Java 16.0.1, Kotlin 1.4.31). `buildConfigField("java.util.Date", "BUILD_TS", "new java.util.Date(" + System.currentTimeMillis().toString() + "L)") ` is what I'm using in my `build.gradle.kts` – nobled Jul 12 '21 at 16:40
  • I suggest removing the old instructions and keeping the latest one only. – Minas Mina Apr 15 '22 at 09:51