extraApps) {
- if (!lpf && !stores && extraApps.isEmpty()) return null;
- for (PirateApp app : getApps(extraApps)) {
- if ((lpf && app.getType() == AppType.PIRATE) ||
- (stores && app.getType() == AppType.STORE) || app.getType() == AppType.OTHER) {
- String pack = app.getPackage();
- 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 (isIntentAvailable(context, intent)) {
- return app;
- }
- } catch (Exception ignored2) {
- try {
- if (hasPermissions(context)) {
- boolean apkExist = false;
- if (apks) {
- 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(context.getFilesDir().getPath() + pack +
- ".apk");
- apkExist = file1.exists() || file2.exists() || file3.exists() ||
- file4.exists() || file5.exists();
- }
-
- boolean foldersExist = false;
- boolean containsFolder = false;
-
- if (folders) {
- File file6 = new File("/data/data/" + pack);
- File file7 = new File(context.getFilesDir().getPath() + pack);
- File file8 =
- new File(Environment.getExternalStorageDirectory() +
- "/Android/data/" + pack);
- foldersExist =
- file6.exists() || file7.exists() || file8.exists();
-
- File appsContainer = new File("/data/app/");
- if (appsContainer.exists()) {
- for (File f : appsContainer.listFiles()) {
- if (f.getName().startsWith(pack))
- containsFolder = true;
- }
- }
- }
-
- if (containsFolder || apkExist || foldersExist) {
- return app;
- }
- }
- } catch (Exception ignored) {
- }
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * Copyright (C) 2013, Vladislav Gingo Skoumal (http://www.skoumal.net)
- */
- static boolean isInEmulator(boolean deepCheck) {
- int ratingCheckEmulator = 0;
-
- if (Build.PRODUCT.contains("sdk") ||
- Build.PRODUCT.contains("Andy") ||
- Build.PRODUCT.contains("ttVM_Hdragon") ||
- Build.PRODUCT.contains("google_sdk") ||
- Build.PRODUCT.contains("Droid4X") ||
- Build.PRODUCT.contains("nox") ||
- Build.PRODUCT.contains("sdk_x86") ||
- Build.PRODUCT.contains("sdk_google") ||
- Build.PRODUCT.contains("vbox86p")) {
- ratingCheckEmulator++;
- }
-
- if (Build.MANUFACTURER.equals("unknown") ||
- Build.MANUFACTURER.equals("Genymotion") ||
- Build.MANUFACTURER.contains("Andy") ||
- Build.MANUFACTURER.contains("MIT") ||
- Build.MANUFACTURER.contains("nox") ||
- Build.MANUFACTURER.contains("TiantianVM")) {
- ratingCheckEmulator++;
- }
-
- if (Build.BRAND.equals("generic") ||
- Build.BRAND.equals("generic_x86") ||
- Build.BRAND.equals("TTVM") ||
- Build.BRAND.contains("Andy")) {
- ratingCheckEmulator++;
- }
-
- if (Build.DEVICE.contains("generic") ||
- Build.DEVICE.contains("generic_x86") ||
- Build.DEVICE.contains("Andy") ||
- Build.DEVICE.contains("ttVM_Hdragon") ||
- Build.DEVICE.contains("Droid4X") ||
- Build.DEVICE.contains("nox") ||
- Build.DEVICE.contains("generic_x86_64") ||
- Build.DEVICE.contains("vbox86p")) {
- ratingCheckEmulator++;
- }
-
- if (Build.MODEL.equals("sdk") ||
- Build.MODEL.equals("google_sdk") ||
- Build.MODEL.contains("Droid4X") ||
- Build.MODEL.contains("TiantianVM") ||
- Build.MODEL.contains("Andy") ||
- Build.MODEL.equals("Android SDK built for x86_64") ||
- Build.MODEL.equals("Android SDK built for x86")) {
- ratingCheckEmulator++;
- }
-
- if (Build.HARDWARE.equals("goldfish") ||
- Build.HARDWARE.equals("vbox86") ||
- Build.HARDWARE.contains("nox") ||
- Build.HARDWARE.contains("ttVM_x86")) {
- ratingCheckEmulator++;
- }
-
- if (Build.FINGERPRINT.contains("generic") ||
- Build.FINGERPRINT.contains("generic/sdk/generic") ||
- Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") ||
- Build.FINGERPRINT.contains("Andy") ||
- Build.FINGERPRINT.contains("ttVM_Hdragon") ||
- Build.FINGERPRINT.contains("generic_x86_64") ||
- Build.FINGERPRINT.contains("generic/google_sdk/generic") ||
- Build.FINGERPRINT.contains("vbox86p") ||
- Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) {
- ratingCheckEmulator++;
- }
-
- if (deepCheck) {
- try {
- String opengl = GLES20.glGetString(GLES20.GL_RENDERER);
- if (opengl != null) {
- if (opengl.contains("Bluestacks") || opengl.contains("Translator"))
- ratingCheckEmulator += 10;
- }
- } catch (Exception ignored) {
- }
-
- try {
- File sharedFolder = new File(Environment.getExternalStorageDirectory().toString()
- + File.separatorChar
- + "windows"
- + File.separatorChar
- + "BstSharedFolder");
- if (sharedFolder.exists())
- ratingCheckEmulator += 10;
- } catch (Exception ignored) {
- }
- }
-
- return ratingCheckEmulator > 3;
- }
-
- static boolean isDebug(Context context) {
- return ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
- }
-
- private static ArrayList getApps(ArrayList extraApps) {
- ArrayList apps = new ArrayList<>();
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "c", "h", "e",
- "l", "p", "u", "s", ".", "l", "a", "c",
- "k", "y", "p", "a", "t", "c", "h"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "d", "i", "m",
- "o", "n", "v", "i", "d", "e", "o", ".",
- "l", "u", "c", "k", "y", "p", "a", "t",
- "c", "h", "e", "r"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "f", "o", "r",
- "p", "d", "a", ".", "l", "p"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "a", "n", "d",
- "r", "o", "i", "d", ".", "v", "e", "n",
- "d", "i", "n", "g", ".", "b", "i", "l",
- "l", "i", "n", "g", ".", "I", "n", "A",
- "p", "p", "B", "i", "l", "l", "i", "n",
- "g", "S", "e", "r", "v", "i", "c", "e",
- ".", "L", "U", "C", "K"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "a", "n", "d",
- "r", "o", "i", "d", ".", "v", "e", "n",
- "d", "i", "n", "g", ".", "b", "i", "l",
- "l", "i", "n", "g", ".", "I", "n", "A",
- "p", "p", "B", "i", "l", "l", "i", "n",
- "g", "S", "e", "r", "v", "i", "c", "e",
- ".", "L", "O", "C", "K"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "a", "n", "d",
- "r", "o", "i", "d", ".", "v", "e", "n",
- "d", "i", "n", "g", ".", "b", "i", "l",
- "l", "i", "n", "g", ".", "I", "n", "A",
- "p", "p", "B", "i", "l", "l", "i", "n",
- "g", "S", "e", "r", "v", "i", "c", "e",
- ".", "L", "A", "C", "K"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "a", "n", "d",
- "r", "o", "i", "d", ".", "v", "e", "n",
- "d", "i", "n", "g", ".", "b", "i", "l",
- "l", "i", "n", "g", ".", "I", "n", "A",
- "p", "p", "B", "i", "l", "l", "i", "n",
- "g", "S", "e", "r", "v", "i", "c", "e",
- ".", "C", "L", "O", "N"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "a", "n", "d",
- "r", "o", "i", "d", ".", "v", "e", "n",
- "d", "i", "n", "g", ".", "b", "i", "l",
- "l", "i", "n", "g", ".", "I", "n", "A",
- "p", "p", "B", "i", "l", "l", "i", "n",
- "g", "S", "e", "r", "v", "i", "c", "e",
- ".", "C", "R", "A", "C"},
- AppType.PIRATE));
- apps.add(new PirateApp("Lucky Patcher", new String[]{"c", "o", "m", ".", "a", "n", "d",
- "r", "o", "i", "d", ".", "v", "e", "n",
- "d", "i", "n", "g", ".", "b", "i", "l",
- "l", "i", "n", "g", ".", "I", "n", "A",
- "p", "p", "B", "i", "l", "l", "i", "n",
- "g", "S", "e", "r", "v", "i", "c", "e",
- ".", "C", "O", "I", "N"},
- AppType.PIRATE));
- apps.add(new PirateApp("Uret Patcher", new String[]{"u", "r", "e", "t", ".", "j", "a",
- "s", "i", "2", "1", "6", "9", ".", "p",
- "a", "t", "c", "h", "e", "r"},
- AppType.PIRATE));
- apps.add(new PirateApp("Freedom", new String[]{"c", "c", ".", "m", "a", "d", "k", "i",
- "t", "e", ".", "f", "r", "e", "e", "d", "o",
- "m"},
- AppType.PIRATE));
- apps.add(new PirateApp("Freedom", new String[]{"c", "c", ".", "c", "z", ".", "m", "a",
- "d", "k", "i", "t", "e", ".", "f", "r", "e",
- "e", "d", "o", "m"},
- AppType.PIRATE));
- apps.add(new PirateApp("CreeHack", new String[]{"o", "r", "g", ".", "c", "r", "e", "e",
- "p", "l", "a", "y", "s", ".", "h", "a", "c",
- "k"},
- AppType.PIRATE));
- apps.add(new PirateApp("HappyMod", new String[]{"c", "o", "m", ".", "h", "a", "p", "p", "y",
- "m", "o", "d", ".", "a", "p", "k"},
- AppType.PIRATE));
- apps.add(new PirateApp("Aptoide", new String[]{"c", "m", ".", "a", "p", "t", "o", "i",
- "d", "e", ".", "p", "t"},
- AppType.STORE));
- apps.add(new PirateApp("BlackMart", new String[]{"o", "r", "g", ".", "b", "l", "a", "c",
- "k", "m", "a", "r", "t", ".", "m", "a",
- "r", "k", "e", "t"},
- AppType.STORE));
- apps.add(new PirateApp("Mobogenie", new String[]{"c", "o", "m", ".", "m", "o", "b", "o",
- "g", "e", "n", "i", "e"},
- AppType.STORE));
- apps.add(new PirateApp("1Mobile", new String[]{"m", "e", ".", "o", "n", "e", "m", "o",
- "b", "i", "l", "e", ".", "a", "n", "d", "r",
- "o", "i", "d"},
- AppType.STORE));
- apps.add(new PirateApp("GetApk", new String[]{"c", "o", "m", ".", "r", "e", "p", "o",
- "d", "r", "o", "i", "d", ".", "a", "p",
- "p"},
- AppType.STORE));
- apps.add(new PirateApp("GetJar", new String[]{"c", "o", "m", ".", "g", "e", "t", "j",
- "a", "r", ".", "r", "e", "w", "a", "r", "d",
- "s"},
- AppType.STORE));
- apps.add(new PirateApp("SlideMe", new String[]{"c", "o", "m", ".", "s", "l", "i", "d",
- "e", "m", "e", ".", "s", "a", "m", ".", "m",
- "a", "n", "a", "g", "e", "r"},
- AppType.STORE));
- apps.add(new PirateApp("ACMarket", new String[]{"n", "e", "t", ".", "a", "p", "p", "c",
- "a", "k", "e"},
- AppType.STORE));
- apps.addAll(extraApps);
- return apps;
- }
-
- private static boolean isIntentAvailable(Context ctx, Intent intent) {
- final PackageManager mgr = ctx.getPackageManager();
- List list = mgr.queryIntentActivities(intent,
- PackageManager.MATCH_DEFAULT_ONLY);
- return list != null && list.size() > 0;
- }
-
- private static boolean hasPermissions(Context context) {
- try {
- return Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN ||
- !shouldAskPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) ||
- (!(ActivityCompat.shouldShowRequestPermissionRationale(
- (Activity) context, Manifest.permission.READ_EXTERNAL_STORAGE)));
- } catch (Exception e) {
- return false;
- }
- }
-
- private static boolean shouldAskPermission() {
- return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
- }
-
- private static boolean shouldAskPermission(Context context, String permission) {
- if (shouldAskPermission()) {
- int permissionResult = ActivityCompat.checkSelfPermission(context, permission);
- return permissionResult != PackageManager.PERMISSION_GRANTED;
- }
- return false;
- }
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyChecker.java b/library/src/main/java/com/github/javiersantos/piracychecker/PiracyChecker.java
deleted file mode 100644
index 7ad87ea..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyChecker.java
+++ /dev/null
@@ -1,420 +0,0 @@
-package com.github.javiersantos.piracychecker;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.provider.Settings;
-import android.support.annotation.ColorRes;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.StringRes;
-import android.util.Log;
-
-import com.github.javiersantos.licensing.AESObfuscator;
-import com.github.javiersantos.licensing.LibraryChecker;
-import com.github.javiersantos.licensing.LibraryCheckerCallback;
-import com.github.javiersantos.licensing.ServerManagedPolicy;
-import com.github.javiersantos.piracychecker.activities.LicenseActivity;
-import com.github.javiersantos.piracychecker.enums.AppType;
-import com.github.javiersantos.piracychecker.enums.Display;
-import com.github.javiersantos.piracychecker.enums.InstallerID;
-import com.github.javiersantos.piracychecker.enums.PiracyCheckerCallback;
-import com.github.javiersantos.piracychecker.enums.PiracyCheckerError;
-import com.github.javiersantos.piracychecker.enums.PirateApp;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-@SuppressWarnings({"WeakerAccess", "unused"})
-@SuppressLint("HardwareIds")
-public class PiracyChecker {
-
- private static final String LIBRARY_PREFERENCES_NAME = "license_check";
-
- // Library configuration/customizations
- private Context context;
- private String unlicensedDialogTitle;
- private String unlicensedDialogDescription;
- private Display display;
- @ColorRes
- private int colorPrimary;
- @ColorRes
- private int colorPrimaryDark;
- private boolean withLightStatusBar;
- @LayoutRes
- private int layoutXML = -1;
- private boolean enableLVL;
- private boolean enableSigningCertificate;
- private boolean enableUnauthorizedAppsCheck;
- private boolean enableStoresCheck;
- private boolean enableEmulatorCheck;
- private boolean enableDeepEmulatorCheck;
- private boolean enableDebugCheck;
- private boolean enableFoldersCheck;
- private boolean enableAPKCheck;
- private boolean saveToSharedPreferences;
- private boolean blockUnauthorized;
- private SharedPreferences preferences;
- private String preferenceSaveResult;
- private String preferenceBlockUnauthorized;
- private String licenseBase64;
- private String signature;
- private List installerIDs;
- private PiracyCheckerCallback callback;
- private ArrayList extraApps;
-
- // LVL
- private LibraryChecker libraryLVLChecker;
- // Dialog
- private PiracyCheckerDialog dialog;
-
- public PiracyChecker(Context context) {
- this(context, context.getString(R.string.app_unlicensed),
- context.getString(R.string.app_unlicensed_description));
- }
-
- public PiracyChecker(Context context, String title, String description) {
- this.context = context;
- this.unlicensedDialogTitle = title;
- this.unlicensedDialogDescription = description;
- this.display = Display.DIALOG;
- this.installerIDs = new ArrayList<>();
- this.extraApps = new ArrayList<>();
- this.colorPrimary = R.color.colorPrimary;
- this.colorPrimaryDark = R.color.colorPrimaryDark;
- }
-
- public PiracyChecker(Context context, @StringRes int title, @StringRes int description) {
- this(context, context.getString(title), context.getString(description));
- }
-
- public PiracyChecker enableGooglePlayLicensing(String licenseKeyBase64) {
- this.enableLVL = true;
- this.licenseBase64 = licenseKeyBase64;
- return this;
- }
-
- public PiracyChecker enableSigningCertificate(String signature) {
- this.enableSigningCertificate = true;
- this.signature = signature;
- return this;
- }
-
- public PiracyChecker enableInstallerId(InstallerID... installerID) {
- this.installerIDs.addAll(Arrays.asList(installerID));
- return this;
- }
-
- @Deprecated
- public PiracyChecker enableUnauthorizedAppsCheck() {
- this.enableUnauthorizedAppsCheck = true;
- return this;
- }
-
- public PiracyChecker enableUnauthorizedAppsCheck(boolean enable) {
- this.enableUnauthorizedAppsCheck = enable;
- return this;
- }
-
- public PiracyChecker blockIfUnauthorizedAppUninstalled(SharedPreferences preferences,
- @NonNull String preferenceName) {
- this.blockUnauthorized = true;
- this.preferenceBlockUnauthorized = preferenceName;
- saveToSharedPreferences(preferences);
- return this;
- }
-
- public PiracyChecker blockIfUnauthorizedAppUninstalled(String preferencesName,
- @NonNull String preferenceName) {
- this.blockUnauthorized = true;
- this.preferenceBlockUnauthorized = preferenceName;
- saveToSharedPreferences(preferencesName);
- return this;
- }
-
- @Deprecated
- public PiracyChecker enableStoresCheck() {
- this.enableStoresCheck = true;
- return this;
- }
-
- @Deprecated
- public PiracyChecker enableDebugCheck() {
- this.enableDebugCheck = true;
- return this;
- }
-
- public PiracyChecker enableStoresCheck(boolean enable) {
- this.enableStoresCheck = enable;
- return this;
- }
-
- public PiracyChecker enableDebugCheck(boolean enable) {
- this.enableDebugCheck = enable;
- return this;
- }
-
- public PiracyChecker enableAPKCheck(boolean enable) {
- this.enableAPKCheck = enable;
- return this;
- }
-
- public PiracyChecker enableEmulatorCheck(boolean deepCheck) {
- this.enableEmulatorCheck = true;
- this.enableDeepEmulatorCheck = deepCheck;
- return this;
- }
-
- public PiracyChecker enableFoldersCheck(boolean foldersCheck) {
- this.enableFoldersCheck = foldersCheck;
- return this;
- }
-
- public PiracyChecker addAppToCheck(PirateApp... apps) {
- this.extraApps.addAll(Arrays.asList(apps));
- return this;
- }
-
- public PiracyChecker saveResultToSharedPreferences(SharedPreferences preferences,
- @NonNull String preferenceName) {
- this.saveToSharedPreferences = true;
- this.preferenceSaveResult = preferenceName;
- saveToSharedPreferences(preferences);
- return this;
- }
-
- public PiracyChecker saveResultToSharedPreferences(String preferencesName,
- @NonNull String preferenceName) {
- this.saveToSharedPreferences = true;
- this.preferenceSaveResult = preferenceName;
- saveToSharedPreferences(preferencesName);
- return this;
- }
-
- private void saveToSharedPreferences(SharedPreferences preferences) {
- if (preferences != null) {
- this.preferences = preferences;
- } else {
- try {
- this.preferences = ((Activity) context).getPreferences(Context.MODE_PRIVATE);
- } catch (Exception e) {
- this.preferences = context.getSharedPreferences(LIBRARY_PREFERENCES_NAME,
- Context.MODE_PRIVATE);
- }
- }
- }
-
- private void saveToSharedPreferences(String preferencesName) {
- if (preferencesName != null) {
- this.preferences = context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE);
- } else {
- try {
- this.preferences = ((Activity) context).getPreferences(Context.MODE_PRIVATE);
- } catch (Exception e) {
- this.preferences = context.getSharedPreferences(LIBRARY_PREFERENCES_NAME,
- Context.MODE_PRIVATE);
- }
- }
- }
-
- public PiracyChecker display(Display display) {
- this.display = display;
- return this;
- }
-
- public PiracyChecker withActivityColors(@ColorRes int colorPrimary,
- @ColorRes int colorPrimaryDark,
- boolean withLightStatusBar) {
- this.colorPrimary = colorPrimary;
- this.colorPrimaryDark = colorPrimaryDark;
- this.withLightStatusBar = withLightStatusBar;
- return this;
- }
-
- public PiracyChecker withActivityLayout(@LayoutRes int layout) {
- this.layoutXML = layout;
- return this;
- }
-
- public PiracyChecker callback(PiracyCheckerCallback callback) {
- this.callback = callback;
- return this;
- }
-
- public void destroy() {
- dismissDialog();
- destroyLVLChecker();
- context = null;
- }
-
- public void start() {
- if (callback == null) {
- this.callback = new PiracyCheckerCallback() {
- @Override
- public void allow() {
- }
-
- @Override
- public void dontAllow(@NonNull PiracyCheckerError error, @Nullable PirateApp app) {
- if (context instanceof Activity && ((Activity) context).isFinishing()) {
- return;
- }
-
- String dialogContent = unlicensedDialogDescription;
- if (app != null)
- dialogContent = context.getString(R.string.unauthorized_app_found,
- app.getName());
- else if (error.equals(PiracyCheckerError.BLOCK_PIRATE_APP))
- dialogContent = context.getString(R.string.unauthorized_app_blocked);
-
- if (display == Display.DIALOG) {
- dismissDialog();
- dialog = PiracyCheckerDialog.newInstance(unlicensedDialogTitle,
- dialogContent);
- if (dialog != null) {
- dialog.show(context);
- } else {
- Log.e("PiracyChecker", "Unlicensed dialog was not built properly. " +
- "Make sure your context is an instance of Activity");
- }
- } else {
- Intent intent = new Intent(context, LicenseActivity.class)
- .putExtra("content", dialogContent)
- .putExtra("colorPrimary", colorPrimary)
- .putExtra("colorPrimaryDark", colorPrimaryDark)
- .putExtra("withLightStatusBar", withLightStatusBar)
- .putExtra("layoutXML", layoutXML);
- context.startActivity(intent);
- if (context instanceof Activity) {
- ((Activity) context).finish();
- }
- destroy();
- }
- }
- };
- }
- verify(callback);
- }
-
- private void verify(final PiracyCheckerCallback verifyCallback) {
- // Library will check first the non-LVL methods since LVL is asynchronous and could take
- // some seconds to give a result
- if (!verifySigningCertificate()) {
- verifyCallback.dontAllow(PiracyCheckerError.SIGNATURE_NOT_VALID, null);
- } else if (!verifyInstallerId()) {
- verifyCallback.dontAllow(PiracyCheckerError.INVALID_INSTALLER_ID, null);
- } else if (!verifyUnauthorizedApp()) {
- verifyCallback.dontAllow(PiracyCheckerError.BLOCK_PIRATE_APP, null);
- } else {
- if (enableLVL) {
- String deviceId = Settings.Secure.getString(context.getContentResolver(),
- Settings.Secure.ANDROID_ID);
- destroyLVLChecker();
- libraryLVLChecker =
- new LibraryChecker(
- context,
- new ServerManagedPolicy(context,
- new AESObfuscator(
- SaltUtils.getSalt(context),
- context.getPackageName(),
- deviceId)),
- licenseBase64);
- libraryLVLChecker.checkAccess(new LibraryCheckerCallback() {
- @Override
- public void allow(int reason) {
- doExtraVerification(verifyCallback, true);
- }
-
- @Override
- public void dontAllow(int reason) {
- doExtraVerification(verifyCallback, false);
- }
-
- @Override
- public void applicationError(int errorCode) {
- verifyCallback.onError(
- PiracyCheckerError.getCheckerErrorFromCode(errorCode));
- }
- });
- } else {
- doExtraVerification(verifyCallback, true);
- }
- }
- }
-
- private boolean verifySigningCertificate() {
- return !enableSigningCertificate ||
- LibraryUtils.verifySigningCertificate(context, signature);
- }
-
- private boolean verifyInstallerId() {
- return installerIDs.isEmpty() || LibraryUtils.verifyInstallerId(context, installerIDs);
- }
-
- private boolean verifyUnauthorizedApp() {
- return !blockUnauthorized || !preferences.getBoolean(preferenceBlockUnauthorized, false);
- }
-
- private void doExtraVerification(PiracyCheckerCallback verifyCallback,
- boolean possibleSuccess) {
- PirateApp app = LibraryUtils.getPirateApp(context, enableUnauthorizedAppsCheck,
- enableStoresCheck, enableFoldersCheck,
- enableAPKCheck, extraApps);
- if (possibleSuccess) {
- if (enableDebugCheck && LibraryUtils.isDebug(context)) {
- if (preferences != null && saveToSharedPreferences)
- preferences.edit().putBoolean(preferenceSaveResult, false).apply();
- verifyCallback.dontAllow(PiracyCheckerError.USING_DEBUG_APP, null);
- } else if (enableEmulatorCheck && LibraryUtils.isInEmulator(enableDeepEmulatorCheck)) {
- if (preferences != null && saveToSharedPreferences)
- preferences.edit().putBoolean(preferenceSaveResult, false).apply();
- verifyCallback.dontAllow(PiracyCheckerError.USING_APP_IN_EMULATOR, null);
- } else if (app != null) {
- if (preferences != null && saveToSharedPreferences)
- preferences.edit().putBoolean(preferenceSaveResult, false).apply();
- if (preferences != null && blockUnauthorized && app.getType() == AppType.PIRATE)
- preferences.edit().putBoolean(preferenceBlockUnauthorized, true).apply();
- verifyCallback.dontAllow(app.getType() == AppType.STORE
- ? PiracyCheckerError.THIRD_PARTY_STORE_INSTALLED
- : PiracyCheckerError.PIRATE_APP_INSTALLED, app);
- } else {
- if (preferences != null && saveToSharedPreferences)
- preferences.edit().putBoolean(preferenceSaveResult, true).apply();
- verifyCallback.allow();
- }
- } else {
- if (app != null) {
- if (preferences != null && saveToSharedPreferences)
- preferences.edit().putBoolean(preferenceSaveResult, false).apply();
- if (preferences != null && blockUnauthorized && app.getType() == AppType.PIRATE)
- preferences.edit().putBoolean(preferenceBlockUnauthorized, true).apply();
- verifyCallback.dontAllow(app.getType() == AppType.STORE
- ? PiracyCheckerError.THIRD_PARTY_STORE_INSTALLED
- : PiracyCheckerError.PIRATE_APP_INSTALLED, app);
- } else {
- if (preferences != null && saveToSharedPreferences)
- preferences.edit().putBoolean(preferenceSaveResult, false).apply();
- verifyCallback.dontAllow(PiracyCheckerError.NOT_LICENSED, null);
- }
- }
- }
-
- private void dismissDialog() {
- if (dialog != null) {
- dialog.dismiss();
- dialog = null;
- }
- }
-
- private void destroyLVLChecker() {
- if (libraryLVLChecker != null) {
- libraryLVLChecker.finishAllChecks();
- libraryLVLChecker.onDestroy();
- libraryLVLChecker = null;
- }
- }
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyChecker.kt b/library/src/main/java/com/github/javiersantos/piracychecker/PiracyChecker.kt
new file mode 100644
index 0000000..0e704b1
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/PiracyChecker.kt
@@ -0,0 +1,470 @@
+package com.github.javiersantos.piracychecker
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.provider.Settings
+import android.support.annotation.ColorRes
+import android.support.annotation.LayoutRes
+import android.support.annotation.StringRes
+import android.util.Log
+import com.github.javiersantos.licensing.AESObfuscator
+import com.github.javiersantos.licensing.LibraryChecker
+import com.github.javiersantos.licensing.LibraryCheckerCallback
+import com.github.javiersantos.licensing.ServerManagedPolicy
+import com.github.javiersantos.piracychecker.activities.LicenseActivity
+import com.github.javiersantos.piracychecker.callbacks.AllowCallback
+import com.github.javiersantos.piracychecker.callbacks.DoNotAllowCallback
+import com.github.javiersantos.piracychecker.callbacks.OnErrorCallback
+import com.github.javiersantos.piracychecker.callbacks.PiracyCheckerCallback
+import com.github.javiersantos.piracychecker.enums.AppType
+import com.github.javiersantos.piracychecker.enums.Display
+import com.github.javiersantos.piracychecker.enums.InstallerID
+import com.github.javiersantos.piracychecker.enums.PiracyCheckerError
+import com.github.javiersantos.piracychecker.enums.PirateApp
+import com.github.javiersantos.piracychecker.utils.SaltUtils
+import com.github.javiersantos.piracychecker.utils.getPirateApp
+import com.github.javiersantos.piracychecker.utils.isDebug
+import com.github.javiersantos.piracychecker.utils.isInEmulator
+import com.github.javiersantos.piracychecker.utils.verifyInstallerId
+import com.github.javiersantos.piracychecker.utils.verifySigningCertificate
+import java.util.ArrayList
+import java.util.Arrays
+
+// Library configuration/customizations
+@Suppress("unused")
+@SuppressLint("HardwareIds")
+class PiracyChecker(
+ private var context: Context?,
+ var unlicensedDialogTitle: String? =
+ context?.getString(R.string.app_unlicensed).orEmpty(),
+ var unlicensedDialogDescription: String? =
+ context?.getString(R.string.app_unlicensed_description).orEmpty()
+ ) {
+
+ private var display: Display? = null
+ @ColorRes
+ private var colorPrimary: Int = 0
+ @ColorRes
+ private var colorPrimaryDark: Int = 0
+ private var withLightStatusBar: Boolean = false
+ @LayoutRes
+ private var layoutXML = -1
+ private var enableLVL: Boolean = false
+ private var enableSigningCertificate: Boolean = false
+ private var enableUnauthorizedAppsCheck: Boolean = false
+ private var enableStoresCheck: Boolean = false
+ private var enableEmulatorCheck: Boolean = false
+ private var enableDeepEmulatorCheck: Boolean = false
+ private var enableDebugCheck: Boolean = false
+ private var enableFoldersCheck: Boolean = false
+ private var enableAPKCheck: Boolean = false
+ private var saveToSharedPreferences: Boolean = false
+ private var blockUnauthorized: Boolean = false
+ private var preferences: SharedPreferences? = null
+ private var preferenceSaveResult: String? = null
+ private var preferenceBlockUnauthorized: String? = null
+ private var licenseBase64: String? = null
+ private var signature: String? = null
+ private val installerIDs: MutableList
+ private val extraApps: ArrayList
+
+ private var allowCallback: AllowCallback? = null
+ private var doNotAllowCallback: DoNotAllowCallback? = null
+ private var onErrorCallback: OnErrorCallback? = null
+
+ // LVL
+ private var libraryLVLChecker: LibraryChecker? = null
+ // Dialog
+ private var dialog: PiracyCheckerDialog? = null
+
+ init {
+ this.display = Display.DIALOG
+ this.installerIDs = ArrayList()
+ this.extraApps = ArrayList()
+ this.colorPrimary = R.color.colorPrimary
+ this.colorPrimaryDark = R.color.colorPrimaryDark
+ }
+
+ constructor(context: Context?) :
+ this(
+ context, context?.getString(R.string.app_unlicensed).orEmpty(),
+ context?.getString(R.string.app_unlicensed_description).orEmpty())
+
+ constructor(context: Context?, title: String?) :
+ this(
+ context, title.orEmpty(),
+ context?.getString(R.string.app_unlicensed_description).orEmpty())
+
+ constructor(context: Context?, @StringRes title: Int) :
+ this(
+ context,
+ if (title != 0) context?.getString(title).orEmpty() else "")
+
+ constructor(context: Context?, @StringRes title: Int, @StringRes description: Int) :
+ this(
+ context,
+ if (title != 0) context?.getString(title).orEmpty() else "",
+ if (description != 0) context?.getString(description).orEmpty() else "")
+
+ fun enableGooglePlayLicensing(licenseKeyBase64: String): PiracyChecker {
+ this.enableLVL = true
+ this.licenseBase64 = licenseKeyBase64
+ return this
+ }
+
+ fun enableSigningCertificate(signature: String): PiracyChecker {
+ this.enableSigningCertificate = true
+ this.signature = signature
+ return this
+ }
+
+ fun enableInstallerId(vararg installerID: InstallerID): PiracyChecker {
+ this.installerIDs.addAll(Arrays.asList(*installerID))
+ return this
+ }
+
+ fun enableUnauthorizedAppsCheck(enable: Boolean = true): PiracyChecker {
+ this.enableUnauthorizedAppsCheck = enable
+ return this
+ }
+
+ fun blockIfUnauthorizedAppUninstalled(
+ preferences: SharedPreferences,
+ preferenceName: String
+ ): PiracyChecker {
+ this.blockUnauthorized = true
+ this.preferenceBlockUnauthorized = preferenceName
+ saveToSharedPreferences(preferences)
+ return this
+ }
+
+ fun blockIfUnauthorizedAppUninstalled(
+ preferencesName: String,
+ preferenceName: String
+ ): PiracyChecker {
+ this.blockUnauthorized = true
+ this.preferenceBlockUnauthorized = preferenceName
+ saveToSharedPreferences(preferencesName)
+ return this
+ }
+
+ fun enableStoresCheck(enable: Boolean = true): PiracyChecker {
+ this.enableStoresCheck = enable
+ return this
+ }
+
+ fun enableDebugCheck(enable: Boolean = true): PiracyChecker {
+ this.enableDebugCheck = enable
+ return this
+ }
+
+ fun enableAPKCheck(enable: Boolean = true): PiracyChecker {
+ this.enableAPKCheck = enable
+ return this
+ }
+
+ fun enableEmulatorCheck(deepCheck: Boolean = true): PiracyChecker {
+ this.enableEmulatorCheck = true
+ this.enableDeepEmulatorCheck = deepCheck
+ return this
+ }
+
+ fun enableFoldersCheck(foldersCheck: Boolean = true): PiracyChecker {
+ this.enableFoldersCheck = foldersCheck
+ return this
+ }
+
+ fun addAppToCheck(vararg apps: PirateApp): PiracyChecker {
+ this.extraApps.addAll(Arrays.asList(*apps))
+ return this
+ }
+
+ fun addAppToCheck(app: PirateApp): PiracyChecker {
+ this.extraApps.add(app)
+ return this
+ }
+
+ fun saveResultToSharedPreferences(
+ preferences: SharedPreferences,
+ preferenceName: String
+ ): PiracyChecker {
+ this.saveToSharedPreferences = true
+ this.preferenceSaveResult = preferenceName
+ saveToSharedPreferences(preferences)
+ return this
+ }
+
+ fun saveResultToSharedPreferences(
+ preferencesName: String,
+ preferenceName: String
+ ): PiracyChecker {
+ this.saveToSharedPreferences = true
+ this.preferenceSaveResult = preferenceName
+ saveToSharedPreferences(preferencesName)
+ return this
+ }
+
+ private fun saveToSharedPreferences(preferences: SharedPreferences?) {
+ if (preferences != null) {
+ this.preferences = preferences
+ } else {
+ try {
+ this.preferences = (context as Activity).getPreferences(Context.MODE_PRIVATE)
+ } catch (e: Exception) {
+ this.preferences = context?.getSharedPreferences(
+ LIBRARY_PREFERENCES_NAME,
+ Context.MODE_PRIVATE)
+ }
+
+ }
+ }
+
+ private fun saveToSharedPreferences(preferencesName: String?) {
+ if (preferencesName != null) {
+ this.preferences = context?.getSharedPreferences(preferencesName, Context.MODE_PRIVATE)
+ } else {
+ try {
+ this.preferences = (context as Activity).getPreferences(Context.MODE_PRIVATE)
+ } catch (e: Exception) {
+ this.preferences = context?.getSharedPreferences(
+ LIBRARY_PREFERENCES_NAME,
+ Context.MODE_PRIVATE)
+ }
+
+ }
+ }
+
+ fun display(display: Display): PiracyChecker {
+ this.display = display
+ return this
+ }
+
+ fun withActivityColors(
+ @ColorRes colorPrimary: Int,
+ @ColorRes colorPrimaryDark: Int,
+ withLightStatusBar: Boolean
+ ): PiracyChecker {
+ this.colorPrimary = colorPrimary
+ this.colorPrimaryDark = colorPrimaryDark
+ this.withLightStatusBar = withLightStatusBar
+ return this
+ }
+
+ fun withActivityLayout(@LayoutRes layout: Int): PiracyChecker {
+ this.layoutXML = layout
+ return this
+ }
+
+ fun allowCallback(allowCallback: AllowCallback): PiracyChecker {
+ this.allowCallback = allowCallback
+ return this
+ }
+
+ fun doNotAllowCallback(doNotAllowCallback: DoNotAllowCallback): PiracyChecker {
+ this.doNotAllowCallback = doNotAllowCallback
+ return this
+ }
+
+ fun onErrorCallback(errorCallback: OnErrorCallback): PiracyChecker {
+ this.onErrorCallback = errorCallback
+ return this
+ }
+
+ fun callback(callback: PiracyCheckerCallback): PiracyChecker {
+ this.allowCallback = object : AllowCallback {
+ override fun allow() {
+ callback.allow()
+ }
+ }
+ this.doNotAllowCallback = object : DoNotAllowCallback {
+ override fun doNotAllow(error: PiracyCheckerError, app: PirateApp?) {
+ callback.doNotAllow(error, app)
+ }
+ }
+ this.onErrorCallback = object : OnErrorCallback {
+ override fun onError(error: PiracyCheckerError) {
+ super.onError(error)
+ callback.onError(error)
+ }
+ }
+ return this
+ }
+
+ fun destroy() {
+ dismissDialog()
+ destroyLVLChecker()
+ context = null
+ }
+
+ fun start() {
+ if (allowCallback == null && doNotAllowCallback == null) {
+ callback(object : PiracyCheckerCallback() {
+ override fun allow() {}
+
+ override fun doNotAllow(error: PiracyCheckerError, app: PirateApp?) {
+ if (context is Activity && (context as Activity).isFinishing) {
+ return
+ }
+
+ val dialogContent = when {
+ app != null ->
+ context?.getString(R.string.unauthorized_app_found, app.name).orEmpty()
+ error == PiracyCheckerError.BLOCK_PIRATE_APP ->
+ context?.getString(R.string.unauthorized_app_blocked).orEmpty()
+ else -> unlicensedDialogDescription
+ }
+
+ if (display == Display.DIALOG) {
+ dismissDialog()
+ dialog = PiracyCheckerDialog.newInstance(
+ unlicensedDialogTitle.orEmpty(), dialogContent.orEmpty())
+
+ context?.let {
+ dialog?.show(it) ?: {
+ Log.e(
+ "PiracyChecker",
+ "Unlicensed dialog was not built properly. Make sure your context is an instance of Activity")
+ }()
+ }
+ } else {
+ val intent = Intent(context, LicenseActivity::class.java)
+ .putExtra("content", dialogContent)
+ .putExtra("colorPrimary", colorPrimary)
+ .putExtra("colorPrimaryDark", colorPrimaryDark)
+ .putExtra("withLightStatusBar", withLightStatusBar)
+ .putExtra("layoutXML", layoutXML)
+ context?.startActivity(intent)
+ if (context is Activity) {
+ (context as Activity).finish()
+ }
+ destroy()
+ }
+ }
+ })
+ }
+ verify()
+ }
+
+ private fun verify() {
+ // Library will check first the non-LVL methods since LVL is asynchronous and could take
+ // some seconds to give a result
+ if (!verifySigningCertificate()) {
+ doNotAllowCallback?.doNotAllow(PiracyCheckerError.SIGNATURE_NOT_VALID, null)
+ } else if (!verifyInstallerId()) {
+ doNotAllowCallback?.doNotAllow(PiracyCheckerError.INVALID_INSTALLER_ID, null)
+ } else if (!verifyUnauthorizedApp()) {
+ doNotAllowCallback?.doNotAllow(PiracyCheckerError.BLOCK_PIRATE_APP, null)
+ } else {
+ if (enableLVL) {
+ val deviceId =
+ Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
+ destroyLVLChecker()
+ libraryLVLChecker =
+ LibraryChecker(
+ context,
+ ServerManagedPolicy(
+ context,
+ AESObfuscator(
+ SaltUtils.getSalt(context), context?.packageName, deviceId)),
+ licenseBase64)
+ libraryLVLChecker?.checkAccess(object : LibraryCheckerCallback {
+ override fun allow(reason: Int) {
+ doExtraVerification(true)
+ }
+
+ override fun dontAllow(reason: Int) {
+ doExtraVerification(false)
+ }
+
+ override fun applicationError(errorCode: Int) {
+ onErrorCallback?.onError(
+ PiracyCheckerError.getCheckerErrorFromCode(errorCode))
+ }
+ })
+ } else {
+ doExtraVerification(true)
+ }
+ }
+ }
+
+ private fun verifySigningCertificate(): Boolean {
+ return !enableSigningCertificate || (context?.verifySigningCertificate(signature) == true)
+ }
+
+ private fun verifyInstallerId(): Boolean {
+ return installerIDs.isEmpty() || (context?.verifyInstallerId(installerIDs) == true)
+ }
+
+ private fun verifyUnauthorizedApp(): Boolean {
+ return !blockUnauthorized ||
+ !(preferences?.getBoolean(preferenceBlockUnauthorized, false) ?: false)
+ }
+
+ private fun doExtraVerification(
+ possibleSuccess: Boolean
+ ) {
+ val app = context?.getPirateApp(
+ enableUnauthorizedAppsCheck, enableStoresCheck, enableFoldersCheck, enableAPKCheck,
+ extraApps)
+ if (possibleSuccess) {
+ if (enableDebugCheck && (context?.isDebug() == true)) {
+ if (preferences != null && saveToSharedPreferences)
+ preferences?.edit()?.putBoolean(preferenceSaveResult, false)?.apply()
+ doNotAllowCallback?.doNotAllow(PiracyCheckerError.USING_DEBUG_APP, null)
+ } else if (enableEmulatorCheck && isInEmulator(
+ enableDeepEmulatorCheck)) {
+ if (preferences != null && saveToSharedPreferences)
+ preferences?.edit()?.putBoolean(preferenceSaveResult, false)?.apply()
+ doNotAllowCallback?.doNotAllow(PiracyCheckerError.USING_APP_IN_EMULATOR, null)
+ } else if (app != null) {
+ if (preferences != null && saveToSharedPreferences)
+ preferences?.edit()?.putBoolean(preferenceSaveResult, false)?.apply()
+ if (preferences != null && blockUnauthorized && app.type == AppType.PIRATE)
+ preferences?.edit()?.putBoolean(preferenceBlockUnauthorized, true)?.apply()
+ doNotAllowCallback?.doNotAllow(
+ if (app.type == AppType.STORE)
+ PiracyCheckerError.THIRD_PARTY_STORE_INSTALLED
+ else
+ PiracyCheckerError.PIRATE_APP_INSTALLED, app)
+ } else {
+ if (preferences != null && saveToSharedPreferences)
+ preferences?.edit()?.putBoolean(preferenceSaveResult, true)?.apply()
+ allowCallback?.allow()
+ }
+ } else {
+ if (app != null) {
+ if (preferences != null && saveToSharedPreferences)
+ preferences?.edit()?.putBoolean(preferenceSaveResult, false)?.apply()
+ if (preferences != null && blockUnauthorized && app.type == AppType.PIRATE)
+ preferences?.edit()?.putBoolean(preferenceBlockUnauthorized, true)?.apply()
+ doNotAllowCallback?.doNotAllow(
+ if (app.type == AppType.STORE)
+ PiracyCheckerError.THIRD_PARTY_STORE_INSTALLED
+ else
+ PiracyCheckerError.PIRATE_APP_INSTALLED, app)
+ } else {
+ if (preferences != null && saveToSharedPreferences)
+ preferences?.edit()?.putBoolean(preferenceSaveResult, false)?.apply()
+ doNotAllowCallback?.doNotAllow(PiracyCheckerError.NOT_LICENSED, null)
+ }
+ }
+ }
+
+ private fun dismissDialog() {
+ dialog?.dismiss()
+ dialog = null
+ }
+
+ private fun destroyLVLChecker() {
+ libraryLVLChecker?.finishAllChecks()
+ libraryLVLChecker?.onDestroy()
+ libraryLVLChecker = null
+ }
+
+ companion object {
+ private const val LIBRARY_PREFERENCES_NAME = "license_check"
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerDialog.java b/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerDialog.java
deleted file mode 100644
index ef8f509..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerDialog.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.github.javiersantos.piracychecker;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-
-public class PiracyCheckerDialog extends DialogFragment {
- private static PiracyCheckerDialog dialog;
- private static String mTitle, mContent;
-
- public PiracyCheckerDialog() {
- }
-
- public static PiracyCheckerDialog newInstance(String dialogTitle, String dialogContent) {
- dialog = new PiracyCheckerDialog();
- mTitle = dialogTitle;
- mContent = dialogContent;
-
- return dialog;
- }
-
- protected void show(Context context) {
- dialog.show(((Activity) context).getFragmentManager(), "[LICENSE_DIALOG]");
- }
-
- @NonNull
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- setCancelable(false);
- return LibraryUtils.buildUnlicensedDialog(getActivity(), mTitle,
- mContent);
- }
-
-}
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerDialog.kt b/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerDialog.kt
new file mode 100644
index 0000000..d4ac958
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerDialog.kt
@@ -0,0 +1,34 @@
+package com.github.javiersantos.piracychecker
+
+import android.app.Activity
+import android.app.Dialog
+import android.app.DialogFragment
+import android.content.Context
+import android.os.Bundle
+import com.github.javiersantos.piracychecker.utils.buildUnlicensedDialog
+
+class PiracyCheckerDialog : DialogFragment() {
+ fun show(context: Context) {
+ (context as? Activity)?.let {
+ pcDialog?.show(it.fragmentManager, "[LICENSE_DIALOG]")
+ }
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle): Dialog? {
+ isCancelable = false
+ return activity.buildUnlicensedDialog(title.orEmpty(), content.orEmpty())
+ }
+
+ companion object {
+ private var pcDialog: PiracyCheckerDialog? = null
+ private var title: String? = null
+ private var content: String? = null
+
+ fun newInstance(dialogTitle: String, dialogContent: String): PiracyCheckerDialog? {
+ pcDialog = PiracyCheckerDialog()
+ title = dialogTitle
+ content = dialogContent
+ return pcDialog
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerUtils.java b/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerUtils.java
deleted file mode 100644
index e0f8a19..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/PiracyCheckerUtils.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.github.javiersantos.piracychecker;
-
-import android.content.Context;
-
-public class PiracyCheckerUtils {
- public static String getAPKSignature(Context context) {
- return LibraryUtils.getCurrentSignature(context);
- }
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/SaltUtils.java b/library/src/main/java/com/github/javiersantos/piracychecker/SaltUtils.java
deleted file mode 100644
index 8717f82..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/SaltUtils.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.github.javiersantos.piracychecker;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-
-import java.util.Random;
-
-/**
- * Credits to Aidan Follestad (afollestad)
- */
-class SaltUtils {
- private static final String KEY_SALT = "piracy-salt";
- private static byte[] mSalt;
-
- private static void generateSalt(Context context) {
- mSalt = new byte[20];
- final Random randomGenerator = new Random();
- for (int i = 0; i < 20; ++i) {
- mSalt[i] = (byte) (randomGenerator.nextInt(600) - 300);
- }
- final String saltStr = getSaltString();
- PreferenceManager.getDefaultSharedPreferences(context)
- .edit().putString(KEY_SALT, saltStr).apply();
- }
-
- private static String getSaltString() {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < mSalt.length; i++) {
- if (i > 0) {
- sb.append(" ");
- }
- sb.append(Byte.toString(mSalt[i]));
- }
- return sb.toString();
- }
-
- private static byte[] bytesFromString(String string) {
- final String[] split = string.split(" ");
- final byte[] data = new byte[split.length];
- for (int i = 0; i < split.length; i++) {
- data[i] = Byte.parseByte(split[i]);
- }
- return data;
- }
-
- @SuppressWarnings("ConstantConditions")
- static byte[] getSalt(Context context) {
- if (mSalt == null) {
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- if (prefs.contains(KEY_SALT)) {
- mSalt = bytesFromString(prefs.getString(KEY_SALT, null));
- }
- if (mSalt == null) {
- generateSalt(context);
- }
- }
- return mSalt;
- }
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/activities/ActivityUtils.java b/library/src/main/java/com/github/javiersantos/piracychecker/activities/ActivityUtils.java
deleted file mode 100644
index b41269d..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/activities/ActivityUtils.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.github.javiersantos.piracychecker.activities;
-
-import android.content.Context;
-import android.os.Build;
-import android.support.annotation.NonNull;
-import android.view.View;
-
-class ActivityUtils {
-
- static String getAppName(Context context) {
- return context.getString(context.getApplicationInfo().labelRes);
- }
-
- static void setupLightStatusBar(@NonNull View view, boolean enable) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- int flags = view.getSystemUiVisibility();
- if (enable)
- flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- else
- flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- view.setSystemUiVisibility(flags);
- }
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/activities/ActivityUtils.kt b/library/src/main/java/com/github/javiersantos/piracychecker/activities/ActivityUtils.kt
new file mode 100644
index 0000000..7a14cd5
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/activities/ActivityUtils.kt
@@ -0,0 +1,18 @@
+package com.github.javiersantos.piracychecker.activities
+
+import android.content.Context
+import android.os.Build
+import android.view.View
+
+fun Context.getAppName(): String = getString(applicationInfo.labelRes)
+
+fun View.setupLightStatusBar(enable: Boolean) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ var flags = systemUiVisibility
+ flags = if (enable)
+ flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
+ else
+ flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
+ systemUiVisibility = flags
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/activities/LicenseActivity.java b/library/src/main/java/com/github/javiersantos/piracychecker/activities/LicenseActivity.java
deleted file mode 100644
index aa131f0..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/activities/LicenseActivity.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.github.javiersantos.piracychecker.activities;
-
-import android.os.Build;
-import android.os.Bundle;
-import android.support.annotation.ColorRes;
-import android.support.annotation.LayoutRes;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import com.github.javiersantos.piracychecker.R;
-
-public class LicenseActivity extends AppCompatActivity {
- private String description;
- @ColorRes
- private int colorPrimary;
- @ColorRes
- private int colorPrimaryDark;
- private boolean withLightStatusBar;
- @LayoutRes
- private int layoutXML;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_license);
- getIntentData();
- setActivityStyle();
- setActivityData();
- }
-
- private void getIntentData() {
- if (getIntent() != null) {
- description = getIntent().getStringExtra("content");
- colorPrimary = getIntent().getIntExtra("colorPrimary",
- ContextCompat
- .getColor(this, R.color.colorPrimary));
- colorPrimaryDark = getIntent().getIntExtra("colorPrimaryDark",
- ContextCompat.getColor(this,
- R.color.colorPrimaryDark));
- withLightStatusBar = getIntent().getBooleanExtra("withLightStatusBar", false);
- layoutXML = getIntent().getIntExtra("layoutXML", -1);
- }
- }
-
- private void setActivityStyle() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- if (toolbar != null) {
- toolbar.setBackgroundColor(ContextCompat.getColor(this, colorPrimary));
- setSupportActionBar(toolbar);
-
- if (getSupportActionBar() != null) {
- getSupportActionBar().setTitle(ActivityUtils.getAppName(this));
- }
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- getWindow().setStatusBarColor(ContextCompat.getColor(this, colorPrimaryDark));
- }
-
- ActivityUtils.setupLightStatusBar(getWindow().getDecorView(), withLightStatusBar);
- }
-
- private void setActivityData() {
- FrameLayout frameLayout = (FrameLayout) findViewById(R.id.mainContainer);
-
- LayoutInflater factory = LayoutInflater.from(this);
- View inflateView;
- if (layoutXML == -1) {
- inflateView = factory.inflate(R.layout.activity_license_default, null);
- TextView activityDescription =
- (TextView) inflateView.findViewById(R.id.piracy_checker_description);
- activityDescription.setText(description);
- } else
- inflateView = factory.inflate(layoutXML, null);
-
- frameLayout.addView(inflateView);
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/activities/LicenseActivity.kt b/library/src/main/java/com/github/javiersantos/piracychecker/activities/LicenseActivity.kt
new file mode 100644
index 0000000..5214d6d
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/activities/LicenseActivity.kt
@@ -0,0 +1,77 @@
+package com.github.javiersantos.piracychecker.activities
+
+import android.annotation.SuppressLint
+import android.os.Build
+import android.os.Bundle
+import android.support.annotation.ColorRes
+import android.support.annotation.LayoutRes
+import android.support.v4.content.ContextCompat
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.Toolbar
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.TextView
+
+import com.github.javiersantos.piracychecker.R
+
+class LicenseActivity : AppCompatActivity() {
+ private var description: String? = null
+ @ColorRes
+ private var colorPrimary: Int = 0
+ @ColorRes
+ private var colorPrimaryDark: Int = 0
+ private var withLightStatusBar: Boolean = false
+ @LayoutRes
+ private var layoutXML: Int = 0
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_license)
+ getIntentData()
+ setActivityStyle()
+ setActivityData()
+ }
+
+ private fun getIntentData() {
+ if (intent != null) {
+ description = intent.getStringExtra("content")
+ colorPrimary = intent.getIntExtra(
+ "colorPrimary", ContextCompat.getColor(this, R.color.colorPrimary))
+ colorPrimaryDark = intent.getIntExtra(
+ "colorPrimaryDark", ContextCompat.getColor(this, R.color.colorPrimaryDark))
+ withLightStatusBar = intent.getBooleanExtra("withLightStatusBar", false)
+ layoutXML = intent.getIntExtra("layoutXML", -1)
+ }
+ }
+
+ private fun setActivityStyle() {
+ val toolbar = findViewById(R.id.toolbar) as? Toolbar
+ toolbar?.setBackgroundColor(ContextCompat.getColor(this, colorPrimary))
+ setSupportActionBar(toolbar)
+ supportActionBar?.title = getAppName()
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ window.statusBarColor = ContextCompat.getColor(this, colorPrimaryDark)
+ }
+
+ window.decorView.setupLightStatusBar(withLightStatusBar)
+ }
+
+ @SuppressLint("InflateParams")
+ private fun setActivityData() {
+ val frameLayout = findViewById(R.id.mainContainer) as FrameLayout
+
+ val factory = LayoutInflater.from(this)
+ val inflateView: View
+ if (layoutXML == -1) {
+ inflateView = factory.inflate(R.layout.activity_license_default, null)
+ val activityDescription =
+ inflateView.findViewById(R.id.piracy_checker_description) as TextView
+ activityDescription.text = description
+ } else
+ inflateView = factory.inflate(layoutXML, null)
+
+ frameLayout.addView(inflateView)
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/callbacks/PiracyCheckerCallbacks.kt b/library/src/main/java/com/github/javiersantos/piracychecker/callbacks/PiracyCheckerCallbacks.kt
new file mode 100644
index 0000000..51e431c
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/callbacks/PiracyCheckerCallbacks.kt
@@ -0,0 +1,47 @@
+package com.github.javiersantos.piracychecker.callbacks
+
+import com.github.javiersantos.piracychecker.enums.PiracyCheckerError
+import com.github.javiersantos.piracychecker.enums.PirateApp
+
+interface AllowCallback {
+ /**
+ * Called after the app checked as valid and licensed
+ */
+ fun allow()
+}
+
+interface DoNotAllowCallback {
+ @Deprecated("dontAllow has been deprecated in favor of doNotAllow", ReplaceWith("doNotAllow"))
+ fun dontAllow(error: PiracyCheckerError, app: PirateApp?) =
+ doNotAllow(error, app)
+
+ /**
+ * Called if the app is not valid or the user is using an unlicensed version. Check errors at
+ * [PiracyCheckerError].
+ *
+ * @param error
+ * PiracyCheckerError.NOT_LICENSED, PiracyCheckerError.SIGNATURE_NOT_VALID or
+ * PiracyCheckerError.INVALID_INSTALLER_ID
+ * @param app
+ * The [PirateApp] that has been detected on device. Returns null in no app was
+ * found.
+ */
+ fun doNotAllow(error: PiracyCheckerError, app: PirateApp?)
+}
+
+interface OnErrorCallback {
+ /**
+ * Called if an error with the license check occurs. Check errors at [ ].
+ *
+ * @param error
+ * PiracyCheckerError.INVALID_PACKAGE_NAME, PiracyCheckerError.NON_MATCHING_UID,
+ * PiracyCheckerError.NOT_MARKET_MANAGED, PiracyCheckerError.CHECK_IN_PROGRESS,
+ * PiracyCheckerError.INVALID_PUBLIC_KEY, PiracyCheckerError.MISSING_PERMISSION or
+ * PiracyCheckerError.UNKNOWN
+ */
+ fun onError(error: PiracyCheckerError) {}
+}
+
+abstract class PiracyCheckerCallback : AllowCallback,
+ DoNotAllowCallback,
+ OnErrorCallback
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/callbacks/PiracyCheckerCallbacksDSL.kt b/library/src/main/java/com/github/javiersantos/piracychecker/callbacks/PiracyCheckerCallbacksDSL.kt
new file mode 100644
index 0000000..0b9d05b
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/callbacks/PiracyCheckerCallbacksDSL.kt
@@ -0,0 +1,14 @@
+package com.github.javiersantos.piracychecker.callbacks
+
+import com.github.javiersantos.piracychecker.PiracyChecker
+
+class PiracyCheckerCallbacksDSL internal constructor(private val checker: PiracyChecker) {
+ fun allow(allowCallback: AllowCallback): PiracyChecker =
+ checker.allowCallback(allowCallback)
+
+ fun doNotAllow(doNotAllowCallback: DoNotAllowCallback): PiracyChecker =
+ checker.doNotAllowCallback(doNotAllowCallback)
+
+ fun onError(onErrorCallback: OnErrorCallback): PiracyChecker =
+ checker.onErrorCallback(onErrorCallback)
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/AppType.java b/library/src/main/java/com/github/javiersantos/piracychecker/enums/AppType.java
deleted file mode 100644
index 5e34ccf..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/enums/AppType.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.github.javiersantos.piracychecker.enums;
-
-public enum AppType {
- PIRATE,
- STORE,
- OTHER
-}
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/AppType.kt b/library/src/main/java/com/github/javiersantos/piracychecker/enums/AppType.kt
new file mode 100644
index 0000000..cc456a4
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/enums/AppType.kt
@@ -0,0 +1,3 @@
+package com.github.javiersantos.piracychecker.enums
+
+enum class AppType { PIRATE, STORE, OTHER }
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/Display.java b/library/src/main/java/com/github/javiersantos/piracychecker/enums/Display.java
deleted file mode 100644
index 6d9af17..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/enums/Display.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.github.javiersantos.piracychecker.enums;
-
-public enum Display {
- DIALOG,
- ACTIVITY
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/Display.kt b/library/src/main/java/com/github/javiersantos/piracychecker/enums/Display.kt
new file mode 100644
index 0000000..b777ef5
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/enums/Display.kt
@@ -0,0 +1,3 @@
+package com.github.javiersantos.piracychecker.enums
+
+enum class Display { DIALOG, ACTIVITY }
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/InstallerID.java b/library/src/main/java/com/github/javiersantos/piracychecker/enums/InstallerID.java
deleted file mode 100644
index 1728c01..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/enums/InstallerID.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.github.javiersantos.piracychecker.enums;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-public enum InstallerID {
- GOOGLE_PLAY("com.android.vending|com.google.android.feedback"),
- AMAZON_APP_STORE("com.amazon.venezia"),
- GALAXY_APPS("com.sec.android.app.samsungapps");
-
- private final String text;
-
- InstallerID(final String text) {
- this.text = text;
- }
-
- /* (non-Javadoc)
- * @see java.lang.Enum#toString()
- */
- @Override
- public String toString() {
- return text;
- }
-
- public List toIDs() {
- if (text.contains("|")) {
- String[] split = text.split("\\|");
- return new ArrayList<>(Arrays.asList(split));
- } else {
- return new ArrayList<>(Collections.singletonList(text));
- }
- }
-
-}
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/InstallerID.kt b/library/src/main/java/com/github/javiersantos/piracychecker/enums/InstallerID.kt
new file mode 100644
index 0000000..a451b60
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/enums/InstallerID.kt
@@ -0,0 +1,24 @@
+package com.github.javiersantos.piracychecker.enums
+
+import java.util.ArrayList
+import java.util.Arrays
+
+enum class InstallerID(private val text: String) {
+ GOOGLE_PLAY("com.android.vending|com.google.android.feedback"),
+ AMAZON_APP_STORE("com.amazon.venezia"),
+ GALAXY_APPS("com.sec.android.app.samsungapps");
+
+ /* (non-Javadoc)
+ * @see java.lang.Enum#toString()
+ */
+ override fun toString(): String {
+ return text
+ }
+
+ fun toIDs(): List = if (text.contains("|")) {
+ val split = text.split("\\|".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ ArrayList(Arrays.asList(*split))
+ } else {
+ ArrayList(listOf(text))
+ }
+}
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerCallback.java b/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerCallback.java
deleted file mode 100644
index 5dd684e..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerCallback.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.github.javiersantos.piracychecker.enums;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-public abstract class PiracyCheckerCallback {
-
- /**
- * Called after the app checked as valid and licensed
- */
- public abstract void allow();
-
- /**
- * Called if the app is not valid or the user is using an unlicensed version. Check errors at
- * {@link PiracyCheckerError}.
- *
- * @param error
- * PiracyCheckerError.NOT_LICENSED, PiracyCheckerError.SIGNATURE_NOT_VALID or
- * PiracyCheckerError.INVALID_INSTALLER_ID
- * @param app
- * The {@link PirateApp} that has been detected on device. Returns null in no app was
- * found.
- */
- public abstract void dontAllow(@NonNull PiracyCheckerError error, @Nullable PirateApp app);
-
-
- /**
- * Called if an error with the license check occurs. Check errors at {@link
- * PiracyCheckerError}.
- *
- * @param error
- * PiracyCheckerError.INVALID_PACKAGE_NAME, PiracyCheckerError.NON_MATCHING_UID,
- * PiracyCheckerError.NOT_MARKET_MANAGED, PiracyCheckerError.CHECK_IN_PROGRESS,
- * PiracyCheckerError.INVALID_PUBLIC_KEY, PiracyCheckerError.MISSING_PERMISSION or
- * PiracyCheckerError.UNKNOWN
- */
- public void onError(@NonNull PiracyCheckerError error) {
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerError.java b/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerError.java
deleted file mode 100644
index 5f77d10..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerError.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.github.javiersantos.piracychecker.enums;
-
-public enum PiracyCheckerError {
- NOT_LICENSED("This user is not using a licensed application from Google Play."),
- SIGNATURE_NOT_VALID("This app is using another signature. The original APK has been modified."),
- INVALID_INSTALLER_ID("This app has been installed from a non-allowed source."),
- USING_DEBUG_APP("This is a debug build."),
- USING_APP_IN_EMULATOR("This app is being used in an emulator."),
- PIRATE_APP_INSTALLED("At least one pirate app has been detected on device."),
- BLOCK_PIRATE_APP(
- "At least one pirate app has been detected and the app must be reinstalled when all " +
- "unauthorized apps are uninstalled.."),
- THIRD_PARTY_STORE_INSTALLED("At least one third-party store has been detected on device."),
-
- // Other errors
- INVALID_PACKAGE_NAME("Application package name is invalid."),
- NON_MATCHING_UID("Application UID doesn\'t match."),
- NOT_MARKET_MANAGED("Not market managed error."),
- CHECK_IN_PROGRESS("License check is in progress."),
- INVALID_PUBLIC_KEY("Application public key is invalid."),
- MISSING_PERMISSION("Application misses the \'com.android.vending.CHECK_LICENSE\' " +
- "permission."),
- UNKNOWN("Unknown error.");
-
- private final String text;
-
- PiracyCheckerError(final String text) {
- this.text = text;
- }
-
- public static PiracyCheckerError getCheckerErrorFromCode(int errorCode) {
- switch (errorCode) {
- case 1:
- return PiracyCheckerError.INVALID_PACKAGE_NAME;
- case 2:
- return PiracyCheckerError.NON_MATCHING_UID;
- case 3:
- return PiracyCheckerError.NOT_MARKET_MANAGED;
- case 4:
- return PiracyCheckerError.CHECK_IN_PROGRESS;
- case 5:
- return PiracyCheckerError.INVALID_PUBLIC_KEY;
- case 6:
- return PiracyCheckerError.MISSING_PERMISSION;
- default:
- return PiracyCheckerError.UNKNOWN;
- }
- }
-
- /* (non-Javadoc)
- * @see java.lang.Enum#toString()
- */
- @Override
- public String toString() {
- return text;
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerError.kt b/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerError.kt
new file mode 100644
index 0000000..01e9e65
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/enums/PiracyCheckerError.kt
@@ -0,0 +1,43 @@
+package com.github.javiersantos.piracychecker.enums
+
+enum class PiracyCheckerError(private val text: String) {
+ NOT_LICENSED("This user is not using a licensed application from Google Play."),
+ SIGNATURE_NOT_VALID("This app is using another signature. The original APK has been modified."),
+ INVALID_INSTALLER_ID("This app has been installed from a non-allowed source."),
+ USING_DEBUG_APP("This is a debug build."),
+ USING_APP_IN_EMULATOR("This app is being used in an emulator."),
+ PIRATE_APP_INSTALLED("At least one pirate app has been detected on device."),
+ BLOCK_PIRATE_APP(
+ "At least one pirate app has been detected and the app must be reinstalled " +
+ "when all unauthorized apps are uninstalled."),
+ THIRD_PARTY_STORE_INSTALLED("At least one third-party store has been detected on device."),
+
+ // Other errors
+ INVALID_PACKAGE_NAME("Application package name is invalid."),
+ NON_MATCHING_UID("Application UID doesn\'t match."),
+ NOT_MARKET_MANAGED("Not market managed error."),
+ CHECK_IN_PROGRESS("License check is in progress."),
+ INVALID_PUBLIC_KEY("Application public key is invalid."),
+ MISSING_PERMISSION("Application misses the \'com.android.vending.CHECK_LICENSE\' " + "permission."),
+ UNKNOWN("Unknown error.");
+
+ /* (non-Javadoc)
+ * @see java.lang.Enum#toString()
+ */
+ override fun toString(): String {
+ return text
+ }
+
+ companion object {
+ fun getCheckerErrorFromCode(errorCode: Int): PiracyCheckerError = when (errorCode) {
+ 1 -> PiracyCheckerError.INVALID_PACKAGE_NAME
+ 2 -> PiracyCheckerError.NON_MATCHING_UID
+ 3 -> PiracyCheckerError.NOT_MARKET_MANAGED
+ 4 -> PiracyCheckerError.CHECK_IN_PROGRESS
+ 5 -> PiracyCheckerError.INVALID_PUBLIC_KEY
+ 6 -> PiracyCheckerError.MISSING_PERMISSION
+ else -> PiracyCheckerError.UNKNOWN
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PirateApp.java b/library/src/main/java/com/github/javiersantos/piracychecker/enums/PirateApp.java
deleted file mode 100644
index 1ba7b05..0000000
--- a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PirateApp.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.github.javiersantos.piracychecker.enums;
-
-import android.support.annotation.NonNull;
-import android.text.TextUtils;
-
-public class PirateApp {
- private String name;
- private String[] pack;
- private AppType type;
-
- public PirateApp(@NonNull String name, @NonNull String[] pack, @NonNull AppType type) {
- this.name = name;
- this.pack = pack;
- this.type = type;
- }
-
- public PirateApp(@NonNull String name, @NonNull String appPackage, @NonNull AppType type) {
- this.name = name;
- this.pack = TextUtils.split(appPackage, "");
- this.type = type;
- }
-
- public PirateApp(@NonNull String name, @NonNull String appPackage) {
- this(name, appPackage, AppType.OTHER);
- }
-
- public String getName() {
- return name;
- }
-
- @Deprecated
- public String[] getPack() {
- return pack;
- }
-
- public String getPackage() {
- StringBuilder sb = new StringBuilder();
- for (String s : pack) {
- sb.append(s);
- }
- return sb.toString();
- }
-
- public AppType getType() {
- return type;
- }
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/enums/PirateApp.kt b/library/src/main/java/com/github/javiersantos/piracychecker/enums/PirateApp.kt
new file mode 100644
index 0000000..6caf7dc
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/enums/PirateApp.kt
@@ -0,0 +1,32 @@
+package com.github.javiersantos.piracychecker.enums
+
+import android.text.TextUtils
+
+class PirateApp(name: String, pack: Array, type: AppType = AppType.OTHER) {
+ var name: String? = null
+ private set
+ var type: AppType? = null
+ private set
+ private var pack: Array? = null
+
+ init {
+ this.name = name
+ this.pack = pack.clone()
+ this.type = type
+ }
+
+ @Deprecated("Deprecated in favor of packageName", ReplaceWith("packageName"))
+ val `package`: String
+ get() = packageName
+
+ val packageName: String
+ get() {
+ val sb = StringBuilder()
+ pack?.forEach { sb.append(it) }
+ return sb.toString()
+ }
+
+ @JvmOverloads
+ constructor(name: String, appPackage: String, type: AppType = AppType.OTHER) :
+ this(name, TextUtils.split(appPackage, ""), type)
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/utils/LibraryUtils.kt b/library/src/main/java/com/github/javiersantos/piracychecker/utils/LibraryUtils.kt
new file mode 100644
index 0000000..b20c304
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/utils/LibraryUtils.kt
@@ -0,0 +1,541 @@
+package com.github.javiersantos.piracychecker.utils
+
+import android.Manifest
+import android.annotation.SuppressLint
+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.PackageManager
+import android.opengl.GLES20
+import android.os.Build
+import android.os.Environment
+import android.support.v4.app.ActivityCompat
+import android.support.v4.app.Fragment
+import android.support.v7.app.AlertDialog
+import android.util.Base64
+import com.github.javiersantos.piracychecker.R
+import com.github.javiersantos.piracychecker.enums.AppType
+import com.github.javiersantos.piracychecker.enums.InstallerID
+import com.github.javiersantos.piracychecker.enums.PirateApp
+import java.io.File
+import java.security.MessageDigest
+import java.util.ArrayList
+
+internal fun Context.buildUnlicensedDialog(title: String, content: String): AlertDialog? {
+ return (this as? Activity)?.let {
+ if (isFinishing) return null
+ AlertDialog.Builder(this)
+ .setCancelable(false)
+ .setTitle(title)
+ .setMessage(content)
+ .setPositiveButton(
+ getString(R.string.app_unlicensed_close),
+ DialogInterface.OnClickListener { _, _ ->
+ if (isFinishing)
+ return@OnClickListener
+ finish()
+ })
+ .create()
+ }
+}
+
+val Context.apkSignature: String
+ get() = currentSignature
+
+val Fragment.apkSignature: String
+ get() = context!!.apkSignature
+
+val Context.currentSignature: String
+ @SuppressLint("PackageManagerGetSignatures")
+ get() {
+ var res = ""
+ try {
+ val packageInfo =
+ packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
+ for (signature in packageInfo.signatures) {
+ val messageDigest = MessageDigest.getInstance("SHA")
+ messageDigest.update(signature.toByteArray())
+ res = Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT)
+ }
+ } catch (ignored: Exception) {
+ }
+ return res.trim()
+ }
+
+internal fun Context.verifySigningCertificate(appSignature: String?): Boolean =
+ appSignature?.let { currentSignature == it } ?: false
+
+internal fun Context.verifyInstallerId(installerID: List): Boolean {
+ val validInstallers = ArrayList()
+ val installer = packageManager.getInstallerPackageName(packageName)
+ for (id in installerID) {
+ validInstallers.addAll(id.toIDs())
+ }
+ return installer != null && validInstallers.contains(installer)
+}
+
+@SuppressLint("SdCardPath")
+internal fun Context.getPirateApp(
+ lpf: Boolean,
+ stores: Boolean,
+ folders: Boolean,
+ apks: Boolean,
+ extraApps: ArrayList
+ ): PirateApp? {
+ if (!lpf && !stores && extraApps.isEmpty()) return null
+
+ val apps = getApps(extraApps)
+ var installed = false
+ var theApp: PirateApp? = null
+
+ try {
+ val pm = packageManager
+ val list = pm?.getInstalledApplications(PackageManager.GET_META_DATA)
+ for (app in apps) {
+ val checkLPF = lpf && app.type == AppType.PIRATE
+ val checkStore = stores && app.type == AppType.STORE
+ val checkOther = app.type == AppType.OTHER
+ if (checkLPF || checkStore || checkOther) {
+ installed = list?.any { it.packageName.contains(app.packageName) } ?: false
+ if (!installed) {
+ installed = isIntentAvailable(pm.getLaunchIntentForPackage(app.packageName))
+ }
+ }
+ if (installed) {
+ theApp = app
+ break
+ }
+ }
+ } catch (e: Exception) {
+ }
+
+ if ((folders || apks) && theApp == null) {
+ if (hasPermissions()) {
+ var apkExist = false
+ var foldersExist = false
+ var containsFolder = false
+
+ for (app in apps) {
+ val pack = app.packageName
+ try {
+ if (apks) {
+ val file1 = File("/data/app/$pack-1/base.apk")
+ val file2 = File("/data/app/$pack-2/base.apk")
+ val file3 = File("/data/app/$pack.apk")
+ val file4 = File("/data/data/$pack.apk")
+ apkExist = file1.exists() || file2.exists() ||
+ file3.exists() || file4.exists()
+ }
+ if (folders) {
+ val file5 = File("/data/data/$pack")
+ val file6 =
+ File(
+ "${Environment.getExternalStorageDirectory()}/Android/data/$pack")
+ foldersExist = file5.exists() || file6.exists()
+
+ val appsContainer = File("/data/app/")
+ if (appsContainer.exists()) {
+ for (f in appsContainer.listFiles()) {
+ if (f.name.startsWith(pack))
+ containsFolder = true
+ }
+ }
+ }
+ } catch (e: Exception) {
+ }
+ if (containsFolder || apkExist || foldersExist) {
+ theApp = app
+ break
+ }
+ }
+ }
+ }
+
+ return theApp
+}
+
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ *
+ * Copyright (C) 2013, Vladislav Gingo Skoumal (http://www.skoumal.net)
+ */
+internal fun isInEmulator(deepCheck: Boolean): Boolean {
+ var ratingCheckEmulator = 0
+
+ if (Build.PRODUCT.contains("sdk") ||
+ Build.PRODUCT.contains("Andy") ||
+ Build.PRODUCT.contains("ttVM_Hdragon") ||
+ Build.PRODUCT.contains("google_sdk") ||
+ Build.PRODUCT.contains("Droid4X") ||
+ Build.PRODUCT.contains("nox") ||
+ Build.PRODUCT.contains("sdk_x86") ||
+ Build.PRODUCT.contains("sdk_google") ||
+ Build.PRODUCT.contains("vbox86p")) {
+ ratingCheckEmulator++
+ }
+
+ if (Build.MANUFACTURER == "unknown" ||
+ Build.MANUFACTURER == "Genymotion" ||
+ Build.MANUFACTURER.contains("Andy") ||
+ Build.MANUFACTURER.contains("MIT") ||
+ Build.MANUFACTURER.contains("nox") ||
+ Build.MANUFACTURER.contains("TiantianVM")) {
+ ratingCheckEmulator++
+ }
+
+ if (Build.BRAND == "generic" ||
+ Build.BRAND == "generic_x86" ||
+ Build.BRAND == "TTVM" ||
+ Build.BRAND.contains("Andy")) {
+ ratingCheckEmulator++
+ }
+
+ if (Build.DEVICE.contains("generic") ||
+ Build.DEVICE.contains("generic_x86") ||
+ Build.DEVICE.contains("Andy") ||
+ Build.DEVICE.contains("ttVM_Hdragon") ||
+ Build.DEVICE.contains("Droid4X") ||
+ Build.DEVICE.contains("nox") ||
+ Build.DEVICE.contains("generic_x86_64") ||
+ Build.DEVICE.contains("vbox86p")) {
+ ratingCheckEmulator++
+ }
+
+ if (Build.MODEL == "sdk" ||
+ Build.MODEL == "google_sdk" ||
+ Build.MODEL.contains("Droid4X") ||
+ Build.MODEL.contains("TiantianVM") ||
+ Build.MODEL.contains("Andy") ||
+ Build.MODEL == "Android SDK built for x86_64" ||
+ Build.MODEL == "Android SDK built for x86") {
+ ratingCheckEmulator++
+ }
+
+ if (Build.HARDWARE == "goldfish" ||
+ Build.HARDWARE == "vbox86" ||
+ Build.HARDWARE.contains("nox") ||
+ Build.HARDWARE.contains("ttVM_x86")) {
+ ratingCheckEmulator++
+ }
+
+ if (Build.FINGERPRINT.contains("generic") ||
+ Build.FINGERPRINT.contains("generic/sdk/generic") ||
+ Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") ||
+ Build.FINGERPRINT.contains("Andy") ||
+ Build.FINGERPRINT.contains("ttVM_Hdragon") ||
+ Build.FINGERPRINT.contains("generic_x86_64") ||
+ Build.FINGERPRINT.contains("generic/google_sdk/generic") ||
+ Build.FINGERPRINT.contains("vbox86p") ||
+ Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) {
+ ratingCheckEmulator++
+ }
+
+ if (deepCheck) {
+ try {
+ val opengl = GLES20.glGetString(GLES20.GL_RENDERER)
+ if (opengl != null) {
+ if (opengl.contains("Bluestacks") || opengl.contains("Translator"))
+ ratingCheckEmulator += 10
+ }
+ } catch (ignored: Exception) {
+ }
+
+ try {
+ val sharedFolder = File(
+ "${Environment.getExternalStorageDirectory()}${File.separatorChar}windows${File.separatorChar}BstSharedFolder")
+ if (sharedFolder.exists())
+ ratingCheckEmulator += 10
+ } catch (ignored: Exception) {
+ }
+ }
+
+ return ratingCheckEmulator > 3
+}
+
+internal fun Context.isDebug(): Boolean =
+ applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
+
+private fun getApps(extraApps: ArrayList): ArrayList {
+ val apps = ArrayList()
+ apps.add(
+ PirateApp(
+ "LuckyPatcher",
+ arrayOf(
+ "c", "o", "m", ".", "c", "h", "e", "l", "p", "u", "s", ".", "l", "a", "c", "k", "y",
+ "p", "a", "t", "c", "h"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "LuckyPatcher",
+ arrayOf(
+ "c", "o", "m", ".", "d", "i", "m", "o", "n", "v", "i", "d", "e", "o", ".", "l", "u",
+ "c", "k", "y", "p", "a", "t", "c", "h", "e", "r"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "LuckyPatcher",
+ arrayOf("c", "o", "m", ".", "f", "o", "r", "p", "d", "a", ".", "l", "p"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "LuckyPatcher",
+ arrayOf(
+ "c", "o", "m", ".", "a", "n", "d", "r", "o", "i", "d", ".", "v", "e", "n", "d", "i",
+ "n", "g", ".", "b", "i", "l", "l", "i", "n", "g", ".", "I", "n", "A", "p", "p", "B",
+ "i", "l", "l", "i", "n", "g", "S", "e", "r", "v", "i", "c", "e"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "LuckyPatcher",
+ arrayOf(
+ "c", "o", "m", ".", "a", "n", "d", "r", "o", "i", "d", ".", "v", "e", "n", "d", "i",
+ "n", "g", ".", "b", "i", "l", "l", "i", "n", "g", ".", "I", "n", "A", "p", "p", "B",
+ "i", "l", "l", "i", "n", "g", "S", "o", "r", "v", "i", "c", "e"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "LuckyPatcher",
+ arrayOf(
+ "c", "o", "m", ".", "a", "n", "d", "r", "o", "i", "d", ".", "v", "e", "n", "d", "i",
+ "n", "c"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "UretPatcher",
+ arrayOf(
+ "u", "r", "e", "t", ".", "j", "a", "s", "i", "2", "1", "6", "9", ".", "p", "a", "t",
+ "c", "h", "e", "r"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "UretPatcher",
+ arrayOf(
+ "z", "o", "n", "e", ".", "j", "a", "s", "i", "2", "1", "6", "9", ".", "u", "r", "e",
+ "t", "p", "a", "t", "c", "h", "e", "r"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "ActionLauncherPatcher",
+ arrayOf("p", ".", "j", "a", "s", "i", "2", "1", "6", "9", ".", "a", "l", "3"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Freedom",
+ arrayOf(
+ "c", "c", ".", "m", "a", "d", "k", "i", "t", "e", ".", "f", "r", "e", "e", "d", "o",
+ "m"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Freedom",
+ arrayOf(
+ "c", "c", ".", "c", "z", ".", "m", "a", "d", "k", "i", "t", "e", ".", "f", "r", "e",
+ "e", "d", "o", "m"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "CreeHack",
+ arrayOf(
+ "o", "r", "g", ".", "c", "r", "e", "e", "p", "l", "a", "y", "s", ".", "h", "a", "c",
+ "k"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "HappyMod",
+ arrayOf("c", "o", "m", ".", "h", "a", "p", "p", "y", "m", "o", "d", ".", "a", "p", "k"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Game Hacker",
+ arrayOf(
+ "o", "r", "g", ".", "s", "b", "t", "o", "o", "l", "s", ".", "g", "a", "m", "e", "h",
+ "a", "c", "k"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Game Killer Cheats",
+ arrayOf(
+ "c", "o", "m", ".", "z", "u", "n", "e", ".", "g", "a", "m", "e", "k", "i", "l", "l",
+ "e", "r"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "AGK - App Killer",
+ arrayOf("c", "o", "m", ".", "a", "a", "g", ".", "k", "i", "l", "l", "e", "r"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Game Killer",
+ arrayOf(
+ "c", "o", "m", ".", "k", "i", "l", "l", "e", "r", "a", "p", "p", ".", "g", "a", "m",
+ "e", "k", "i", "l", "l", "e", "r"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Game Killer", arrayOf("c", "n", ".", "l", "m", ".", "s", "q"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Game CheatIng Hacker",
+ arrayOf(
+ "n", "e", "t", ".", "s", "c", "h", "w", "a", "r", "z", "i", "s", ".", "g", "a", "m",
+ "e", "_", "c", "i", "h"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Game Hacker",
+ arrayOf(
+ "c", "o", "m", ".", "b", "a", "s", "e", "a", "p", "p", "f", "u", "l", "l", ".", "f",
+ "w", "d"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Content Guard Disabler",
+ arrayOf(
+ "c", "o", "m", ".", "g", "i", "t", "h", "u", "b", ".", "o", "n", "e", "m", "i", "n",
+ "u", "s", "o", "n", "e", ".", "d", "i", "s", "a", "b", "l", "e", "c", "o", "n", "t",
+ "e", "n", "t", "g", "u", "a", "r", "d"),
+ AppType.PIRATE))
+
+ apps.add(
+ PirateApp(
+ "Content Guard Disabler",
+ arrayOf(
+ "c", "o", "m", ".", "o", "n", "e", "m", "i", "n", "u", "s", "o", "n", "e", ".", "d",
+ "i", "s", "a", "b", "l", "e", "c", "o", "n", "t", "e", "n", "t", "g", "u", "a", "r",
+ "d"),
+ AppType.PIRATE))
+ apps.add(
+ PirateApp(
+ "Aptoide", arrayOf("c", "m", ".", "a", "p", "t", "o", "i", "d", "e", ".", "p", "t"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "BlackMart",
+ arrayOf(
+ "o", "r", "g", ".", "b", "l", "a", "c", "k", "m", "a", "r", "t", ".", "m", "a", "r",
+ "k", "e", "t"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "BlackMart",
+ arrayOf(
+ "c", "o", "m", ".", "b", "l", "a", "c", "k", "m", "a", "r", "t", "a", "l", "p", "h",
+ "a"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "Mobogenie",
+ arrayOf("c", "o", "m", ".", "m", "o", "b", "o", "g", "e", "n", "i", "e"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "1Mobile",
+ arrayOf(
+ "m", "e", ".", "o", "n", "e", "m", "o", "b", "i", "l", "e", ".", "a", "n", "d", "r",
+ "o", "i", "d"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "GetApk", arrayOf(
+ "c", "o", "m", ".", "r", "e", "p", "o", "d", "r", "o", "i", "d", ".", "a", "p", "p"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "GetJar",
+ arrayOf(
+ "c", "o", "m", ".", "g", "e", "t", "j", "a", "r", ".", "r", "e", "w", "a", "r", "d",
+ "s"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "SlideMe",
+ arrayOf(
+ "c", "o", "m", ".", "s", "l", "i", "d", "e", "m", "e", ".", "s", "a", "m", ".", "m",
+ "a", "n", "a", "g", "e", "r"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "ACMarket",
+ arrayOf("n", "e", "t", ".", "a", "p", "p", "c", "a", "k", "e"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "ACMarket",
+ arrayOf("a", "c", ".", "m", "a", "r", "k", "e", "t", ".", "s", "t", "o", "r", "e"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "AppCake",
+ arrayOf("c", "o", "m", ".", "a", "p", "p", "c", "a", "k", "e"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "Z Market",
+ arrayOf("c", "o", "m", ".", "z", "m", "a", "p", "p"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "Modded Play Store",
+ arrayOf(
+ "c", "o", "m", ".", "d", "v", ".", "m", "a", "r", "k", "e", "t", "m", "o", "d", ".",
+ "i", "n", "s", "t", "a", "l", "l", "e", "r"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "Mobilism Market",
+ arrayOf(
+ "o", "r", "g", ".", "m", "o", "b", "i", "l", "i", "s", "m", ".", "a", "n", "d", "r",
+ "o", "i", "d"),
+ AppType.STORE))
+ apps.add(
+ PirateApp(
+ "All-in-one Downloader", arrayOf(
+ "c", "o", "m", ".", "a", "l", "l", "i", "n", "o", "n", "e", ".", "f", "r", "e", "e"),
+ AppType.STORE))
+ apps.addAll(extraApps)
+ return ArrayList(apps.distinctBy { it.packageName })
+}
+
+private fun Context.isIntentAvailable(intent: Intent?): Boolean {
+ return try {
+ val list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
+ list?.isNotEmpty() ?: false
+ } catch (e: Exception) {
+ false
+ }
+}
+
+private fun Context.hasPermissions(): Boolean {
+ return try {
+ Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN ||
+ !shouldAskPermission(Manifest.permission.READ_EXTERNAL_STORAGE) ||
+ !ActivityCompat.shouldShowRequestPermissionRationale(
+ this as Activity, Manifest.permission.READ_EXTERNAL_STORAGE)
+ } catch (e: Exception) {
+ false
+ }
+}
+
+private fun shouldAskPermission(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+
+private fun Context.shouldAskPermission(permission: String): Boolean {
+ if (shouldAskPermission()) {
+ val permissionResult = ActivityCompat.checkSelfPermission(this, permission)
+ return permissionResult != PackageManager.PERMISSION_GRANTED
+ }
+ return false
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/github/javiersantos/piracychecker/utils/SaltUtils.kt b/library/src/main/java/com/github/javiersantos/piracychecker/utils/SaltUtils.kt
new file mode 100644
index 0000000..8e0a3c7
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/piracychecker/utils/SaltUtils.kt
@@ -0,0 +1,74 @@
+package com.github.javiersantos.piracychecker.utils
+
+import android.content.Context
+import android.preference.PreferenceManager
+import java.util.Random
+
+/**
+ * Credits to Aidan Follestad (afollestad)
+ */
+internal object SaltUtils {
+ private const val KEY_SALT = "salty-salt"
+ private var mSalt: ByteArray? = null
+
+ private val saltString: String
+ get() {
+ val sb = StringBuilder()
+ mSalt?.let {
+ for (i in it.indices) {
+ if (i > 0) {
+ sb.append(" ")
+ }
+ sb.append(java.lang.Byte.toString(it[i]))
+ }
+ }
+ return sb.toString()
+ }
+
+ private fun generateSalt(context: Context?) {
+ mSalt = ByteArray(20)
+ val randomGenerator = Random()
+ mSalt?.let {
+ for (i in 0..19) {
+ it[i] = (randomGenerator.nextInt(600) - 300).toByte()
+ }
+ }
+ context ?: return
+ val saltStr = saltString
+ PreferenceManager.getDefaultSharedPreferences(context)
+ .edit().putString(KEY_SALT, saltStr)
+ .apply()
+ }
+
+ private fun bytesFromString(string: String): ByteArray {
+ val split = string.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ val data = ByteArray(split.size)
+ for (i in split.indices) {
+ data[i] = java.lang.Byte.parseByte(split[i])
+ }
+ return data
+ }
+
+ fun getSalt(context: Context?): ByteArray? {
+ if (mSalt == null) {
+ mSalt = context?.let {
+ try {
+ val prefs = PreferenceManager.getDefaultSharedPreferences(context)
+ if (prefs.contains(
+ KEY_SALT)) {
+ bytesFromString(
+ prefs.getString(
+ KEY_SALT,
+ null))
+ } else null
+ } catch (e: Exception) {
+ null
+ }
+ }
+ if (mSalt == null) {
+ generateSalt(context)
+ }
+ }
+ return mSalt
+ }
+}
\ No newline at end of file