Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added extra checks and option to save result to SharedPreferences #15

Merged
merged 18 commits into from
Mar 13, 2017
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 67 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ dependencies {

## Usage
Add **CHECK_LICENSE** permission to your app's Manifest:

```xml
<uses-permission android:name="com.android.vending.CHECK_LICENSE"/>
```

*Note: this may not be really required and adding it allows LuckyPatcher to detect your app. Try yourself and decide.*

### Verify Google Play Licensing (LVL)
Google Play offers a licensing service that lets you enforce licensing policies for applications that you publish on Google Play. With Google Play Licensing, your application can query Google Play to obtain the licensing status for the current user.

Expand Down Expand Up @@ -88,6 +91,58 @@ new PiracyChecker(this)

**BE CAREFUL!!** This is a really restrictive technique since it will block your app from being installed using another market or directly installing the .apk on the device. It isn't recommended for most cases.

### Verify the use of certain pirate apps
If you want to check if user has pirate apps installed, you can use this code.
It will check for: Lucky Patcher, Freedom and CreeHack.

```Java
new PiracyChecker(this)
.enableLPFCheck(true)
.start();
```

If you want to check if user has third-party store apps installed, you can use this code.
It will check for: Aptoide, BlackMart, Mobogenie, 1Mobile, GetApk, GetJar and SlideMe.

```Java
new PiracyChecker(this)
.enableStoresCheck(true)
.start();
```

### Verify if app is a debug build.
```Java
new PiracyChecker(this)
.enableDebugCheck(true)
.start();
```

### Verify if app is being run in an emulator
```Java
new PiracyChecker(this)
.enableEmulatorCheck(true)
.start();
```

### Save the result of the license check in `SharedPreferences`

There are two ways to do this:

Define the `SharedPreferences` and the name of the preference where you want to save the result.
```Java
new PiracyChecker(this)
.saveResultToSharedPreferences(preferences, "valid_license");
.start();
```

Define the `SharedPreferences` name and the name of the preference where you want to save the result.
```Java
new PiracyChecker(this)
.saveResultToSharedPreferences("my_app_preferences", "valid_license");
.start();
```


## Customizations
Adding a callback to the builder allows you to customize what will happen when the license has been checked and manage the license check errors if the user is not allowed to use the app. Keep in mind that when using this method **you must be aware of blocking the app from unauthorized users**.

Expand All @@ -103,13 +158,18 @@ Use the builder and add following:
}

@Override
public void dontAllow(PiracyCheckerError error) {
public void dontAllow(@NonNull PiracyCheckerError error, @Nullable PirateApp app) {
// You can either do something specific when the user is not allowed to use the app
// Or manage the error, using the 'error' parameter, yourself (Check errors at {@link PiracyCheckerError}).

// Additionally, if you enabled the check of pirate apps and/or third-party stores, the 'app' param
// is the app that has been detected on device. App can be null, and when null, it means no pirate app or store was found,
// or you disabled the check for those apps.
// This allows you to let users know the possible reasons why license is been invalid.
}

@Override
public void onError(PiracyCheckerError error) {
public void onError(@NonNull PiracyCheckerError error) {
// This method is not required to be implemented/overriden but...
// You can either do something specific when an error occurs while checking the license,
// Or manage the error, using the 'error' parameter, yourself (Check errors at {@link PiracyCheckerError}).
Expand All @@ -119,10 +179,8 @@ Use the builder and add following:

## ProGuard
```
-keep class com.google.**
-keep class autovalue.shaded.com.google.**
-dontwarn com.google.**
-dontwarn autovalue.shaded.com.google.**
-keep class com.github.javiersantos.**
-dontwarn com.github.javiersantos.**
-keep public class com.android.vending.licensing.ILicensingService
```

Expand All @@ -134,11 +192,13 @@ Sure. You can use as many validation methods in the builder as you want. For exa
new PiracyChecker(this)
.enableGooglePlayLicensing("BASE_64_LICENSE_KEY")
.enableSigningCertificate("YOUR_APK_SIGNATURE")
.enableLPFCheck(true)
.saveResultToSharedPreferences("my_app_preferences", "valid_license");
.start();
```

## License
Copyright 2016 Javier Santos
Copyright 2017 Javier Santos

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
android:label="@string/action_about"/>
</application>

</manifest>
</manifest>
3 changes: 3 additions & 0 deletions library/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@
# public *;
#}

# Lib
-keep class com.github.javiersantos.**
-dontwarn com.github.javiersantos.**
# LVL
-keep public class com.android.vending.licensing.ILicensingService
5 changes: 1 addition & 4 deletions library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.javiersantos.piracychecker" >
<uses-permission android:name="com.android.vending.CHECK_LICENSE"/>
</manifest>
<manifest package="com.github.javiersantos.piracychecker"/>
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.support.v7.app.AlertDialog;
import android.util.Base64;

import com.github.javiersantos.piracychecker.R;
import com.github.javiersantos.piracychecker.enums.InstallerID;
import com.github.javiersantos.piracychecker.enums.PirateApp;

import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
Expand Down Expand Up @@ -45,7 +51,6 @@ public void onClick(DialogInterface dialogInterface, int i) {

static String getCurrentSignature(Context context) {
String res = "";

try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context
.getPackageName(), PackageManager.GET_SIGNATURES);
Expand All @@ -56,7 +61,6 @@ static String getCurrentSignature(Context context) {
}
} catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException ignored) {
}

return res.trim();
}

Expand All @@ -76,4 +80,77 @@ static boolean verifyInstallerId(Context context, List<InstallerID> installerID)
return installer != null && validInstallers.contains(installer);
}

}
@SuppressLint("SdCardPath")
static PirateApp getPirateApp(Context context, boolean lpf, boolean stores) {
if (!lpf && !stores) return null;
for (PirateApp app : PiracyCheckerUtils.getApps()) {
if ((lpf && app.isLPF()) || (stores && !app.isLPF())) {
StringBuilder builder = new StringBuilder();
for (String s : app.getPack()) {
builder.append(s);
}
String pack = builder.toString();
PackageManager pm = context.getPackageManager();
try {
PackageInfo info = pm.getPackageInfo(pack, PackageManager.GET_META_DATA);
if (info != null) return app;
} catch (PackageManager.NameNotFoundException ignored1) {
try {
Intent intent = pm.getLaunchIntentForPackage(pack);
if (PiracyCheckerUtils.isIntentAvailable(context, intent)) {
return app;
}
} catch (Exception ignored2) {
try {
if (PiracyCheckerUtils.hasPermissions(context)) {
File file1 = new File("/data/app/" + pack + "-1/base.apk");
File file2 = new File("/data/app/" + pack + "-2/base.apk");
File file3 = new File("/data/app/" + pack + ".apk");
File file4 = new File("/data/data/" + pack + ".apk");
File file5 = new File("/data/data/" + pack);
File file6 = new File(context.getFilesDir().getPath() + pack +
".apk");
File file7 = new File(context.getFilesDir().getPath() + pack);
File file8 = new File(Environment.getExternalStorageDirectory() +
"/Android/data/" + pack);
if (file1.exists() || file2.exists() || file3.exists() ||
file4.exists() || file5.exists() || file6.exists() ||
file7.exists() || file8.exists()) {
return app;
}
}
} catch (Exception ignored3) {
}
}
}
}
}
return null;
}

static boolean isInEmulator() {
try {
boolean goldfish = PiracyCheckerUtils.getSystemProperty("ro.hardware")
.contains("goldfish");
boolean emu = PiracyCheckerUtils.getSystemProperty("ro.kernel.qemu").length() > 0;
boolean sdk = PiracyCheckerUtils.getSystemProperty("ro.product.model").equals("sdk");
if (emu || goldfish || sdk) {
return true;
}
} catch (Exception ignored) {
}
return false;
}

static boolean isDebug(Context context) {
return ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
}

static boolean isConnectedToInternet(Context context) {
Copy link
Owner

@javiersantos javiersantos Mar 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConnectivityManager will check if the user has WiFi or data enabled. If LuckyPatcher or any other patcher uses an offline mode, this method will return true because the device is connected to the Internet.

This method doesn't fix the issue reported by @franciscofranco , since the license checker will return "Allow" when the user is connected to the Internet and using a simple bypass by LuckyPatcher (offline mode).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind if I ask you for a suggestion?

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context
.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

}
Loading