No, we could just store some key in the preferences to make sure that the preference file hasn't been blindly deleted. It's not perfect, it's just meant to be a deterrent. (If we're providing an initial grace period, we've already established that the application isn't highly concerned about the security of the license check -- and a deterrent is still better than the alternative.)
-- Trevor Johns Google Developer Programs, Android http://developer.android.com On Wed, Jul 28, 2010 at 4:00 PM, Mark Carter <[email protected]> wrote: > How does that trip wire work? If the user clears the app data, then surely > the only way you could tell is by storing something outside of the app's > scope (like on the server or in the Market app). > > I'd be happy to contribute LenientPolicy. Actually modified it today so > that it caches LICENSED and NOT_LICENSED responses (in the same way as > ServerManagedPolicy) so that it doesn't have to call the server every time. > This means LenientPolicy now uses the Obfuscator and no longer stores any > non-obfuscated prefs. I'm happy to do the Javadoc but don't really have time > to do the JUnit tests. Anyway, shouldn't someone other than the implementer > do those? ;) > > On 29 July 2010 00:43, Trevor Johns <[email protected]> wrote: > >> I was considering writing something like this into the library, but it >> wasn't a priority since I figured somebody would be able to defeat it easily >> (as you mentioned ;)). If you be willing to clean it up (add JavaDocs and >> JUnit tests) and sign a CLA, I'd be happy to accept it as a contribution for >> a future release. Assuming you were amenable to the idea, of course. >> >> That being said, I'm currently working on a patch to ServerManagedPolicy >> that will allow specifying an initial grace period in case the user is >> offline during the initial license check. It will also have a tripwire that >> can optionally delete an application's data if it detects the licensing >> shared preferences have been deleted -- a consequence for trying to take >> advantage of the grace period as a workaround. Since that's at the top of my >> list, there's a very good chance that will be in r2 of the library. >> >> -- >> Trevor Johns >> Google Developer Programs, Android >> http://developer.android.com >> >> On Wed, Jul 28, 2010 at 8:41 AM, Mark Carter <[email protected]>wrote: >> >>> I've been playing around with the new LVL announced yesterday and >>> wanted to write a policy which only stops the user when it is certain >>> that he does not have a license. >>> >>> In other words, the policy will only "dontAllow" the user if the last >>> meaningful response from the licensing service was NOT_LICENSED. >>> Therefore, if the user is offline when they first use the app, then >>> they will be allowed in. >>> >>> The idea behind this is that I don't want genuine paying users to ever >>> (within reason) be inconvenienced by this licensing system. >>> >>> The downside is that all the user needs to do is clear the app data >>> and go offline before restarting the app. The app will continue >>> working until they go online (and restart the app). >>> >>> My thoughts are: >>> >>> 1. Most users won't know about that workaround >>> 2. Those users that are happy to use that workaround, probably >>> wouldn't pay for the app anyway >>> >>> Any other thoughts? >>> >>> === >>> >>> Here is the code: >>> >>> public void processServerResponse(LicenseResponse response, >>> ResponseData rawData) { >>> mLastResponse = response; >>> if (response == LicenseResponse.LICENSED || response == >>> LicenseResponse.NOT_LICENSED) { >>> // note - we don't want to say "IS_LICENSED" because that >>> can be >>> hacked >>> SharedPreferences prefs = >>> PreferenceManager.getDefaultSharedPreferences(this.mContext); >>> Editor edit = prefs.edit(); >>> if (response == LicenseResponse.LICENSED) { >>> edit.remove(NOT_LICENSED_PREF); >>> } else if (response == LicenseResponse.NOT_LICENSED) { >>> edit.putBoolean(NOT_LICENSED_PREF, true); >>> } >>> edit.commit(); >>> } >>> } >>> >>> public boolean allowAccess() { >>> if (mLastResponse == null) { >>> // this is the first call >>> return false; >>> } >>> switch (mLastResponse) { >>> case LICENSED: >>> return true; >>> case NOT_LICENSED: >>> return false; >>> default: >>> return !isDefinitelyNotLicensed(); >>> } >>> } >>> >>> public boolean isDefinitelyNotLicensed() { >>> // if we don't know, then its NOT definitely not licensed. >>> SharedPreferences prefs = >>> PreferenceManager.getDefaultSharedPreferences(mContext); >>> return prefs.getBoolean(NOT_LICENSED_PREF, false); >>> } >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Android Developers" group. >>> To post to this group, send email to [email protected] >>> To unsubscribe from this group, send email to >>> [email protected]<android-developers%[email protected]> >>> For more options, visit this group at >>> http://groups.google.com/group/android-developers?hl=en >>> >> >> >> >> >> >> > -- Trevor Johns -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en

